NEXFLEX ๊ณผ์
โ๏ธ ์ค๋ ๋ฐฐ์ด context API๋ฅผ ํ์ฉํด์ ๋๋ค์์ ์์ ํ ์ ์๊ณ , ํค๋์ ๋๋ค์์ ๋์์ผํ๋ฉฐ
์ข์์๋ฒํผ๊ณผ ์ข์์ ์ทจ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ์ด์๋ค.
HomePage์์ ์ข์์, ์ข์์ ์ทจ์๋ฅผ ๋๋ฅด๋ฉด
๋ง์ดํ์ด์ง์ ์ด์ ๊ฐ์ด ์ข์์ํ ์ํ ๋ชฉ๋ก๋ค์ด ๋ด๊ฒจ์ผํ๋ค.
๋ฌผ๋ก ์์ธํ์ด์ง์์๋ ์ข์์๊ฐ ๋ ์ํ๋ผ๋ฉด ํ์๋์ด์ผํ๋ค.
๐ ๊ฐ์ฌ๋์ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด ๋ฆฌํฉํ ๋ง ํด๋ณด์
๐ ์ข์์ ๋ฒํผ์ ํ ๊ธ๋ก ๊ตฌํํ๋ฉฐ, likedMovies์ ์ ์ญ์ํ๋ฅผ ์ ๋ฐ์ดํธ ํด์ผํ๋ค.
{!likedMovies.some((likedMovie) => likedMovie.title === movie.title)
? <LikedBtn></LikedBtn>
: <UnlikedBtn></UnlikedBtn>
some()์ผ๋ก ์ข์์ํ ์ํ๋ค์ด ๋ด๊ธด likedMovie์ ํ์ฌ ํด๋ฆญ๋ movied๊ฐ ์ผ์น์ฌ๋ถ(boolean)์ผ๋ก ์ฌ์ฉํด ์ข์์๋ฒํผ๊ณผ ์ทจ์ ๋ฒํผ์ ๋ ๋๋งํ๋ค.
โ๏ธ ์ด๋ฌํ ๋ฐฉ๋ฒ์ ๋ฆฌ๋ ๋๋ง ๋๋ค๋ฉด, ์ปดํฌ๋ํธํจ์ ์์ ์๊ธฐ ๋๋ฌธ์ ์ด ์ฐ์ฐ์ ๋ฆฌ๋ ๋๋งํ ๋๋ง๋ค ํ ๊ฒ์ด๋ค.
โจ ์ข์์, ์ทจ์ ๋ฒํผ์ ์ด๋ ๊ฒ ๋ฐ๋ก ๋ง๋๋๊ฒ์ด ์๋๋ผ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํด์ ํ๋๋ก ๋ง๋ค์ด boolean์ผ๋ก ๊ด๋ฆฌํ๋ค.
์ด์ฐจํผ ๋ง์ ํ์ด์ง์์ ์ค๋ณตํด์ ๊ณ์ ์ฌ์ฉ๋๋ฉฐ, ์ปดํฌ๋ํธ๋ก ๋ฐ๋ก ๋ถ๋ฆฌํ๋ฉด ๋ฒํผ์ ๋๋ฅผ๋๋ง๋ค ์ปจํ ์ธ ๋ค์ด ๋ฆฌ๋ ๋๋ง์ด ๋๋๊ฒ ์๋๋ผ ๋ฒํผ๋ง ๋ฆฌ๋ ๋๋ง์ด ์ผ์ด๋ ๊ฒ์ด๋ค.
์ข์์, ์ทจ์๋ฅผ ์ํด isLiked(boolean)๋ก ๊ด๋ฆฌํ๋ค.
const isLiked=!! likedMovies.find((likedMovie.id===movie.id)
์ด๋์ ์ปดํฌ๋ํธ ๋ถ๋ฆฌ๋ฅผ ๊ฐ๋ ์ฑ๋ , ์ฑ๋ฅ๋ฉด์์๋ ์ค์ํ๋ค...
๐ nickName์ input์ฐฝ์ ์ ๋ ฅํ๊ณ , ์์ ๋ฒํผ์ ํด๋ฆญํ ๋๋ง ๋ ๋๋ง๋๊ฒ ํ๊ณ ์ถ๋ค.
const [inputNickName, setInputNickName] = useState("");
const handleClickNickName = (e) => {
e.preventDefault();
setNickName(inputNickName);
};
<NickNameInput
onChange={(e) => setInputNickName(e.target.value)}
value={inputNickName}
id="nickName"
type="text"
placeholder="๋๋ค์์ ์ค์ ํด์ฃผ์ธ์"
/>
input์ฐฝ์ change ํธ๋ค๋ฌ ํจ์๋ก ๋ณํ๋๋ ๊ฐ์ value๋ฅผ ๋ฐ์ click์ด ๋ ๋, nickName์ ์ ์ญ์ํ๊ฐ์ ๋ณ๊ฒฝํ๋ ๋ฐฉ์์ผ๋ก ๋ง๋ค์๋ค.
โ๏ธ์ด๋ ๊ฒ ํ๋ฉด, ํ๊ธ์์ฉ ์ ๋ ฅํ ๋๋ง๋ค state ๊ฐ์ ์ ๋ฐ์ดํธ ํ๊ธฐ ๋๋ฌธ์ ๋ฆฌ๋ ๋๋ง์ด ๊ณ์ํด์ ๋ฐ์ํ๋ค.
๐๐ป useEffect๋ฅผ ์ฌ์ฉํด ์ ๋ฐ์ดํธ ํ๋ ๋ฐฉ์๋ ์๊ณ ,
๐๐ป useRef๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. useRef๋ useState์ ์ ์ฌํ์ง๋ง, ์ํ๊ฐ์ด ๋ณํ ๋๋ง๋ค ๋ ๋๋ง๋๋ ๋ฐฉ์๊ณผ ์ฐจ์ด๊ฐ ์๋ค.
๊ทธ๋์ ๋ ๋๋ง์ด ๋์ง ์๊ธธ ๋ฐ๋๋ useRef๋ฅผ ์ฌ์ฉํ๋ค.
input์ด ๋ฆฌ๋ ๋๋ง์ ๋ง์ด ์ ๋ฐํ๊ธฐ ๋๋ฌธ์, useRef๋ฅผ ์ฌ์ฉํ๋ค!
โจ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ ์๋ค. ํ์ฌ ๋ง์ดํ์ด์ง์ input์ ์ํด ๋ฆฌ๋ ๋๋ง๋๋ฉด์ ๋ฐ์ ์๋ ์ข์์ ์ํ๋ชฉ๋ก๋ค ๋ํ ๊ณ์ ๋ฆฌ๋ ๋๋ง ๋๊ณ ์๋๋ฐ, input์ ์ปดํฌ๋ํธ ๋ถ๋ฆฌํ๊ณ input์ ๋ํ state ๊ด๋ฆฌ๋ฅผ ํ๋ค๋ฉด, input ์ปดํฌ๋ํธ ํจ์๋ง ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ ํ ๋ ๊ฐ์ ํ์ด์ง ๋ด์ ์ํ๋ชฉ๋ก๋ค์ด ๋ฆฌ๋ ๋๋ง ๋๋๊ฒ์ ๋ง์ ์์์ ๊ฒ์ด๋ค. ์ง๊ธ๊ฐ์ด ํํ์ด์ง์ ์จ์ผํ๋ค๋ฉด ๋ฒํผ ํด๋ฆญ์์๋ง ๋ฆฌ๋ ๋๋ง ๋๋๋ก useRef๋ฅผ ์ฐ์.
โ ๊ฐ์ฒด๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง ๋๊ฒจ์ฃผ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ฌธ์ ๊ฐ ํฌ๊ฒ ๋ฐ์ํ์ง ์๋๋ค๊ณ ํ๋ค.
Redux
์๋ฒ์ฌ์ด๋ ์ํ๊ด๋ฆฌ → React Query
ํด๋ผ์ด์ธํธ์ฌ์ดํธ ์ํ๊ด๋ฆฌ → Redux , zustand
โก๏ธ ๋ฆฌ๋์ค๋ ๋จ๋ฐฉํฅ์ผ๋ก ํ๋ฌ๊ฐ๊ธฐ ๋๋ฌธ์, ๋๋ฒ๊น ํ๊ธฐ์ ์ฉ์ดํ๋ค.
npm install @reduxjs/toolkit
npm install react-redux
๊ฐ๋
๐ญ ๊ณต์ฅ = Reducer
๐ ๋ฐ์ดํฐ ์ ์ฅ์= store
๐ ์์ ์ง์์ = Action
- ๐ ์์ ์ข ๋ฅ: action type
- ๐ ์์ ํ์ ๋ฐ์ดํฐ : payload
๐ฎ ์ฐ์ฒด๋ถ(์ ๋ฌํ์)=dispatch
โโจ Yuuuki๋ผ๋ ์น๊ตฌ(์ปดํฌ๋ํธ)๊ฐ ์ค๋์ ์ ์ฌ ๋ฉ๋ด๐(state)๋ฅผ ๋ฐ๊พธ๊ณ ์ถ๋ค. redux๋ ๊น๊นํ ์ฌ๋์ด๊ธฐ ๋๋ฌธ์ ์์ ์ง์์(type+data)๋ฅผ ์์ฑํด์ ์ฐ์ฒด๋ถ์๊ฒ ๋ณด๋ด์ผ๋ง, ์ค๋์ ์ ์ฌ ์ํ๋ฅผ ๋ณ๊ฒฝํด์ค๋ค.
ํ์ผ ๊ตฌ์กฐ
๐src
ใด ๐redux
ใด ๐reducers
ใด ๐character.reducer.js
๐ store.js
//index.js
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route element={<DefaultLayout />}>
<Route path="/" element={<HomePage />}></Route>
</Route>
</Routes>
</BrowserRouter>
</Provider>
redux๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด provider๋ก ๊ฐ์ธ์ค๋ค.
App์์ Provider๋ฅผ ๊ฐ์ธ์ง ์๋ ์ด์
//store.js
import { configureStore } from "@reduxjs/toolkit";
import characterReducer from "./reducers/character.reducer";
//๊ณต์ฅ(reducer)๊ด๋ฆฌ
const store = configureStore({
reducer: {
character: characterReducer,
},
});
export default store;
configureStore ํจ์๋ฅผ ํธ์ถํ์ฌ store๋ฅผ ์ค์ ํฉ๋๋ค.
reducer ์์ฑ์๋ ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ reducer ํจ์๋ค์ ํฌํจํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({ reducer });
const initalState = {
count: 0,
};
//๊ณต์ฅ(reducer) ์์ฑ
function reducer(state = initalState, action) {
//action name
switch (action.type) {
case "SAY_HELLO":
console.log("HELLO");
return state;
case "INCREMENT":
//๋ถ๋ณ์ฑ ์ ์ง๋ฅผ ์ํด์
// state.count += 1;
const newState = { ...state, count: state.count + 1 };
return newState;
default:
return state;
}
}
export default store;
๊ณต์ฅ์ ํจ์์ด๋ฉฐ, state์ action์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์์ state์ action(์์ ์ง์์)๋ฅผ ์ํํ๋ค.
switch๋ฌธ์ผ๋ก ๊ณต์ฅ์ ๋ค์ด์ค๋ ์ํํด์ผํ action.type์ ๋ฐ๋ผ case๋ฅผ ์ ์ํ๋ค.
//character.reducer.js
//action type ๋ณ์ ์ง์
export const MOVE = "MOVE";
//์ด๊ธฐ๊ฐ ์ ์
const initalState = {
level: 1,
location: { x: 0, y: 0 },
horizontalDirection: "right",
};
//action ์์ฑ์ํจ์ (์์
์ง์์ ์์ฑ) : type,payload ๋ด์์ ์์
์ง์์ ์์ฑ
export const moveActionCreator = (direction) => ({
type: MOVE,
payload: direction,
horizontalDirection: "right",
});
//๊ณต์ฅ(reducer)ํจ์
function characterReducer(state = initalState, action) {
switch (action.type) {
case MOVE:
const newLocation = { ...state.location };
//ํค์ ๋ฐ๋ผ state ๋ณ๊ฒฝ ๋ก์ง
if (action.payload === "up") {
--newLocation.y;
}else if (action.payload === "right") {
++newLocation.y;
}
//state ์
๋ฐ์ดํธ
const newState={
...state,
location:newLocation
}
return newState;
default:
return state;
}
Action creator
export const moveActionCreator = (direction) => ({
type: MOVE,
payload: direction,
horizontalDirection: "right",
});
์ก์ ์์ฑ = ์์ ์ง์์๐ ์์ฑํ๋ ํจ์์ด๋ค.
์์ ์ง์์๋ฅผ ์์ฑํด์ store์ dispatchํ ์ ์๋๋ก ๋์์ฃผ๋ ํจ์
โtype, payload(๋ฐ์ดํฐ)๋ฅผ ๋ด๋๋ค.
์ด์๊ฐ์ด ์ถ๊ฐ์ ์ธ ๋ฐ์ดํฐ(horizontalDirection)๋ ๋ด์์ ์๋ค๊ณ ํ๋ค.
useSelector
๊ฐ์ ๊บผ๋ด ์ฌ์ฉํ๊ณ ์ถ์๋ useSelector๋ฅผ ์ฌ์ฉํ๋๋ฐ
๊บผ๋ด์ ์ฌ์ฉํ๊ณ ์ถ์ ์ ์ญ์ํ๋ state.reducer(๊ณต์ฅ)์ด๋ฆ.๊บผ๋ด๊ณ ์ถ์ state์ด๋ฆ๋ก ๊บผ๋ธ๋ค.
//const selectedState = useSelector(selectorFunction);
const location = useSelector((state) => state.character.location);
useDispatch
action์ dispatchํ๋๋ฐ ์ฌ์ฉ๋๋ ํจ์ = ์์ ์ง์์๋ฅผ ์ฐ์ฒด๊ตญ์ผ๋ก ๋ณด๋ด๋ ํจ์๋ก์จ,
์ด๋ฅผ ์ฌ์ฉํด dispatchํจ์๋ฅผ ์ฌ์ฉํ ์์๋ค (์ฐ์ฒด๊ตญ ๋ง๋ค๊ธฐ)
import { useDispatch } from 'react-redux';
const YourComponent = () => {
const dispatch = useDispatch();
const handleClick = () => {
// ์ก์
๋์คํจ์น ์์
dispatch({ type: 'SOME_ACTION' });
//dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data })
};
return (
<button onClick={handleClick}>
Dispatch Action
</button>
);
};
โ dispatch ํจ์๋ action์ store์ ์ ๋ฌํ์ฌ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ์ญํ ์ ํ๋ฉฐ, ์ํ ๋ณ๊ฒฝ์ ๋ฐ๋ผ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ์ํค๋ ์ญํ ์ ํ๋ค.
๋งค๊ฐ๋ณ์์ action์ (type,payload๊ฐ ๋ด๊ธด)๊ฐ์ฒด๋ฅผ ๋ฃ์ด์ค๋ค.