Node Sass version 5.0.0 is incompatible with ^4.0.0.
node-sass๋ฅผ ์ต์ ๋ฒ์ ์ผ๋ก ์ค์นํ๋ฉด 5.0.0๋ฒ์ ์ด ์ค์น๋๋๋ฐ ์ด๋๋ก ์คํํ๋ฉด ์์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ๋ฒ์ ํธํ์ด ์ ์๋๋์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง ์ต์ ๋ฒ์ ์ ์ง์ฐ๊ณ ์์ ๋ฒ์ ์ ๋ค์ด๋ฐ๋๋ค.
ํด๊ฒฐ๋ฐฉ๋ฒ
yarn remove node-sass
yarn add [email protected]
img elements must have an alt prop, either with meaningful text, or an empty string for decorative images jsx-a11y/alt-text
<img className="social-image" src={NaverLogo} alt="NaverLogo" />
rgba๋ก ์ํ๊ฐ์ ์ง์ ํด์ฃผ๋ฉด ์๋ ํด๋น ์ปฌ๋ฌ์๋ง ์ ์ฉ๋๋ค.
โ div๋ด์ ํ ์คํธ๋ ํฌ๋ช ํด์ง์ง ์๊ณ div๋ฐฐ๊ฒฝ ์ปฌ๋ฌ๋ง ํฌ๋ช ํด์ง.
ํด๊ฒฐ๋ฐฉ๋ฒ
โ rgba๋์ opacity๋ฅผ ์ฌ์ฉํ๋ค. opacity๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ํด๋น ๊ฐ์ฒด ๋ด์ ์๋ ๋ชจ๋ ์์๋ค์ด ํจ๊ฒ ํฌ๋ช ํด์ง๋ค.
โ ํ์ง๋ง!! ๊ฐ์ฒด ๋ด ์์๋ค์ด ํฌ๋ช ํด์ง๋๊ฑธ ์์น ์๋๋ค๋ฉด ๊ทธ๋ฅ rgb๋ hex๋ก ์ ์ง์ ํด์ผ๋จ
state๋ณ์์ ํจ์๋ฅผ file, setFile๋ก ์ง์ ํ๋ ํด๋น ์ค๋ฅ ๋ฐ์
ํด๊ฒฐ๋ฐฉ๋ฒ
๋ณ์์ ํจ์๋ช ์ uploadFile, setUploadFile๋ก ๋ฐ๊ฟ
์๋ฌธ์
์ด๋๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์๋๋ฐ ๋ณ์๋ช ๋ค์ file๋ก ๋ฐ๊ฟ๋ณด๋๊น ์ง๊ธ์ ๋ ์ ๋์ํจ..์ ์ ์๋ค.
#์ ์๋์ผ๋ก ์ ๋ ฅํ๊ธฐ ์ํด์ value์ ๋ง์ง๋ง ์์๊ฐ์ด ' '์ผ ๊ฒฝ์ฐ value์ #๋ฅผ ๋ถ์
โ ์ด๋ ๊ฒ ํ ๊ฒฝ์ฐ ๋น์ฐํ #๋ฅผ ์ง์ ์ ๊ฒฝ์ฐ์๋ ๋ง์ง๋ง ์์๊ฐ ' '์ด๊ธฐ ๋๋ฌธ์ #์ด ๊ณ์ ๋ค์ ๋ถ๋๋ค.
// useInputs.js
else if (name === 'keywords' && value[length - 1] === ' ') {
dispatch({ type: 'CHANGE', name, value: value + '#' });
}
ํด๊ฒฐ ๋ฐฉ๋ฒ
value์ ๋ง์ง๋ง ์์๊ฐ์ผ๋ก ํ์ธํ์ง ๋ง๊ณ ' '๊ฐ ์ ๋ ฅ๋์ ๊ฒฝ์ฐ์ #์ ๋ถ์ผ ์ ์๋๋ก ํ๋ค.
โ ํค์ ์ ๋ ฅ๊ฐ์ ํ์ธํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ ์์ฑ์ด๋ค. ์ ๋ ฅ์ฐฝ์ ํค๊ฐ ๋๋ ธ์๋๋ง ์ด๋ฒคํธ๊ฐ ๋ฐ์๋๋ค.
handleKeyPress = (e) => {
if (e.key === "Enter") {
...
}
};
<input
...
onKeyPress={this.handleKeyPress}
/>
โ ์ผ๋ฐ์ ์ผ๋ก๋ ํค์ ์ ๋ ฅ๊ฐ์ ํ์ธํ ๋ ํด๋น ์์ฑ์ ์ฌ์ฉํ์ง ์๋๋ค.
ํ์ง๋ง ์ํฐ๊ฐ ์ ๋ ฅ๋์๋ ์๋์ผ๋ก #๋ฅผ ์ ๋ ฅํ๋ ๊ฒ์ด ๋ชฉ์ ์ด์๊ธฐ ๋๋ฌธ์ useInputs.js์ ๊ตฌํ๋ onChangeํจ์์์ ํค๊ฐ์ ํ์ธํด์ผ ํ๋ค.
onChange์ ์ด๋ฒคํธ๊ฐ์ ๋ก๊ทธ์ ์ถ๋ ฅํด๋ดค์๋ e.nativeEvent.data์ ์ ๋ ฅ๊ฐ์ด ๋ค์ด๊ฐ๋๊ฑธ ๋ณด๊ณ ํด๋น ์์ฑ์ผ๋ก ์ ๋ ฅ๊ฐ์ ํ์ธํ๋ฉด ๋๋ค๊ณ ์๊ฐํ๋ค.
// useInputs.js
else if (name === 'keywords' && e.nativeEvent.data === ' ') {
dispatch({ type: 'CHANGE', name, value: value + '#' });
}
์์ด๋ก ์ ๋ ฅํ๋ฉด ํ๋ฒ๋ง ๋จ๋๋ฐ ํ๊ธ๋ก ์น๋ฉด ์ฌ๋ฌ๋ฒ ๋ฌ๋ค ์ด์ ๋ ๋ชจ๋ฆ
์ค๋ฅ์ด์ : 20์๋ฅผ ๋์ผ๋ฉด title์ ๋ณ๊ฒฝํ์ง ์๊ธฐ ๋๋ฌธ์ useInputs์ onChange์์ value๋ฅผ ํ์ธํ์๋ 21์๊น์ง๋ง ๋์์ผ ๋จ, ๊ทผ๋ฐ ์ค์ ๋ก ํ์ธํด๋ณด๋ฉด ๊ทธ๋ ์ง ์์, ๊ณ์ ์ ๋ ฅ๋๊ณ ์์
โ ํ๊ธ์ 1๊ธ์๋ฅผ ์ ๋ ฅํ๋คํด๋ ์์, ๋ชจ์์ด ์ฌ๋ฌ๊ฐ ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ ํจ์๊ฐ ์ฌ๋ฌ๋ฒ ํธ์ถ๋จ
'์ผ์ผ'๋ผ๊ณ ์ ๋ ฅํ ๊ฒฝ์ฐ '์'์ ์ ๋ ฅํ ํ์ 'ใ '๋ฅผ ์ ๋ ฅํ ๋ ํจ์๊ฐ ์ธ๋ฒ ํธ์ถ๋จ

์ค๋ฅํ๋ฉด

setTimeout์ ์ฌ์ฉํด์ ์๊ฐ์ฐจ๋ฅผ ๋๊ฒ ํ๋ค.
โ ์ฒ์์๋ง ์๋จ๊ณ ํ๋ฒ ๋จ๊ณ ๋๋ฉด ์ฐ์์ ์ผ๋ก ๊ณ์ ๋ฌ๋ค
value์ length๊ฐ ์๋ byte๋ก ์ ๋ ฅ์ ์ ํ์ํจ๋ค.
โ length๋ก ํ ๋๋ ๋๊ฐ์ด ์ฌ๋ฌ๋ฒ ํธ์ถ๋จ.
// signup.js
const handleSignup = () => {
const signupDt = new Date().toISOString();
axios
.post('<http://52.78.77.73:8080/user/signup>', {
email: email,
name: nickname,
pwd: password,
signId: id,
signupDt: signupDt,
})
.then((response) => {
if (response.data === -1) {
alert(Words.DUPLICATE_ID);
} else {
alert(Words.SUCCESS_SIGNUP);
history.push('/login');
}
})
.catch((error) => {
console.log(error);
});
};
์ค๋ฅ ์ด์ : useAsync์ useEffect์์ deps๋ฅผ []์์ ๋ฃ์ด๋์ ๊ทธ๋ฐ๊ฑฐ์์, deps๋ ์๋ ๋ฐฐ์ด ํํ๋ก ๋ค์ด์ค๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด์ ๋ ์์์๋ ๋๋ค..๋ฐ๋ณด์ผ..!!
// useAsync.js
useEffect(() => {
if (skip) return;
fetchData();
}, deps);
์ปค์คํ Hook์ผ๋ก ์์ฑํด์ ๋ฐ์ํ๋ ๋ฌธ์ , ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ๋ถ๋ฅด๋ฉด ๋ฐ์ดํฐ ์๋ฐ์์ด
useEffect(() => {
axios
.get('<http://52.78.77.73:8080/category>')
.then((response) => {
console.log(response.data);
})
.catch((error) => {
alert('์๋ฌ ๋ฐ์');
});
});
ํด๊ฒฐ๋ฐฉ๋ฒ: ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก์ ์ ์ฅํ๋ context api๋ฅผ ์์ฑํ๊ณ CategoryList ์ปดํฌ๋ํธ์์ ์ต์ด ๋ ๋๋ง๋ ์์ ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก์ ๊ธธ์ด๊ฐ 1์ผ ๊ฒฝ์ฐ์๋ง api๋ฅผ ํธ์ถํ๋๋ก ํ๋ค.
// CategoryContext.js
const initialState = {
categoryList: [{ id: 0, title: '์ ์ฒด' }],
currentCategoryId: 0,
};
function categoryReducer(state, action) {
switch (action.type) {
case 'SET_CATEGORY_LIST':
return {
...state,
// concat์ ๋ฐฐ์ด๊ณผ ๋ฐฐ์ด์ ํฉ์ณ์ฃผ๋ ํจ์
categoryList: state.categoryList.concat(action.value),
};
case 'SET_CURRENT_CATEGORY':
return {
...state,
currentCategoryId: action.value,
};
default:
throw new Error(`Unhandled action type: ${action.type}`);
}
}
// CategoryList.js
useEffect(() => {
async function getCategoryList() {
const response = await axios.get('<http://52.78.77.73:8080/category>');
categoryDispatch({ type: 'SET_CATEGORY_LIST', value: response.data });
}
if (categoryList.length === 1) {
getCategoryList();
}
}, [categoryList, categoryDispatch]);