일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 내일배움캠프 최종 프로젝트
- 파이썬 slice
- typeScript
- 자바스크립트
- JavaScript
- 파이썬 딕셔너리
- 파이썬 enumerate
- 파이썬 for
- 리액트 공식문서
- useState
- 코딩테스트
- useEffect
- 리액트 프로젝트
- 리액트
- 프로그래머스
- 타입스크립트
- 내일배움캠프 프로젝트
- tanstack query
- 내배캠 프로젝트
- 파이썬 for in
- 파이썬 반복문
- 리액트 훅
- 타입스크립트 리액트
- 파이썬 replace
- Next 팀 프로젝트
- REACT
- 내일배움캠프
- React Hooks
- 한글 공부 사이트
- 타입스크립트 props
- Today
- Total
sohyeon kim
[React] Redux(1) : useSelector, useDispatch, 중앙 데이터 관리 본문
💡 리덕스를 활용해 보자~
props 를 넘겨주는 방식은 계속 지나쳐가는(props 를 넘겨주기만 하는) 컴포넌트가 생길 수 있다.
중앙 데이터 관리소 store 를 만들어서 데이터를 한 번에 가져올 수 있도록 연결해 주자.
👀 그런데 Context API 말고 Redux 를 쓰는 이유는?
1. 성능 최적화
Context API 는 Provider 하위 모든 컴포넌트를 리렌더링하게 할 수 있다.
그래서 불필요한 업데이트를 막기 위한 복잡한 최적화 과정이 필요하지만
Redux 는 상태 변경 시 관련 컴포넌트만 선택적으로 업데이트할 수 있어 성능 관리에 용이하다.
2. 상태 로직의 중앙화와 일관성
Redux 는 앱의 상태를 하나의 저장소 store 에 저장하기 때문에 상태 고직이 중앙에서 관리되어
더 일관성 있고 예층 가능한 상태 변경이 가능해진다.
또한, 모튼 상태 변경 로직이 리듀서 Reducers 에 의해 처리되기 때문에 디버깅과 테스팅에 용이하다.
3. 강력한 미들웨어와 개발 도구
Redux 는 다양한 미들웨어를 지원하여 비동기 작업, 로깅, 상태 변경에 대한 추가 처리 등
복잡한 기능을 구현할 수 있다. 또한, Redux DevTools 와 같은 강력한 개발 도구를 통해
상태 변화를 시각적으로 모니터링하고 이전 상태로 롤백하는 등의 기능을 제공한다.
npm add redux react-redux
- redex 폴더 : 리덕스 관련 모든 코드들이 들어가는 곳
- config 폴더 : 리덕스 설정 관련 파일이 들어가는 곳
- configStore.js : 중앙 state(data) 관리소
- modules 폴더 : state 의 그룹! Todolist 라면 Todo.js 등
configStore.js
import { createStore } from "redux"; // 새 스토어를 만들어 줄 API
import { combineReducers } from "redux"; // reducer 들을 합쳐줄 API
import counter from "../modules/counter";
import users from "../modules/users";
const rootReducer = combineReducers({ counter, users }); // 합친 reducer 들을 rootReducer 로 저장
const store = createStore(rootReducer); // 그 rootReducer 로 이루어진 store
export default store;
새 스토어를 만들었고, 이제 연결하자. (리듀서는 만드는 건 아래에!)
index.jsx
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux"; {/*import*/}
import store from "./redux/config/configStore"; {/*import*/}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}> {/*지배권 행사하는 Provider 로 하위 컴포넌트를 감싼다.*/}
<App /> {/*하위 컴포넌트에서 store 에 접근이 가능해진다.*/}
</Provider>
);
modules 폴더에 그룹을 만들어보자.
counter.js, users.js
const initialState = { // 초기 상태값 설정(state)
number: 0,
};
// 리듀서(counter) : 'state 에 변화를 일으키는'함수
// 'state 를 action 의 type 에 따라 변경하는' 함수
// input 으로 state, action 을 받는다.
// state 에 설정해 둔 초기값을 넣는다.
// action 은 type 과 value 를 가지는데 이걸로 state 를 어떻게 바꿀건지를 정한다.
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state; // 우선 초기값 리턴하도록 함
}
};
export default counter;
const initialState = {
userId: 123,
};
const users = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
export default users;
App 에서 reducer(counter, users) 들의 데이터를 읽어오자.
App.jsx
import "./App.css";
import { useSelector } from "react-redux"; {/*store에 접근해, reducer 의 값을 읽어온다.*/}
function App() {
const data = useSelector((state) => { {/*여기서 state 는 중앙 관리소의 전체 데이터들*/}
return state; {/*그대로 리턴해서*/}
});
console.log(data); {/*출력해보자.*/}
return (
<>
<div>Redux~~~~~~~~~</div>
</>
);
}
export default App;
// 카운터의 데이터만 가져오고 싶다면
const data = useSelector((state) => {
return state.counter;
});
➡️ {number: 0} 출력
💡 데이터를 변경해 보자!
App.js
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
function App() {
const counter = useSelector((state) => {
return state.counter;
});
const dispatch = useDispatch(); {/*store 에 바뀐 값을 전달해 줌*/}
return (
<>
<div>현재 카운트 : {counter.number}</div>
<button
onClick={() => {
dispatch({ type: "PLUS_ONE" }); {/*action 에 보낼 값*/}
}}
>
+
</button>
</>
);
}
export default App;
counter.js
const initialState = {
number: 0,
};
const counter = (state = initialState, action) => {
switch (action.type) {
case "PLUS_ONE": // 액션의 타입이 PLUS_ONE 으로 전달되면
return { number: state.number + 1 }; // number 가 + 1 된 새 객체를 반환한다.
default:
return state;
}
};
export default counter;
❗️ 그런데 위와 같이 타입을 문자열로 전달해 주면
전달해 준 값이 많아지고, 변경할 시 하나하나 수정하기 힘들어진다.
그러니 상수로 지정해 넘겨주자.
counter.js
export const PLUS_ONE = "PLUS_ONE"; // 상수 만들고, App 에서도 써야 하니 export!
const initialState = {
number: 0,
};
const counter = (state = initialState, action) => {
switch (action.type) {
case PLUS_ONE:
return { number: state.number + 1 };
default:
return state;
}
};
export default counter;
App.jsx
import { PLUS_ONE } from "./redux/modules/counter";
...
return (
<>
<div>현재 카운트 : {counter.number}</div>
<button
onClick={() => {
dispatch({ type: PLUS_ONE }); {/*가져온 상수로 타입 보냄*/}
}}
>
+
</button>
);
그럼 똑같이 동작한다!
❗️ 여기서 한번 더.. 리팩토링
dispatch 가 액션 객체를 넘겨주고 있는데, 그 객체에 전달해 줄 값이 많아질 수 있다.
type 말고도 더.. 그걸 함수(action creater)로 관리해 보자.
counter.js
// action value
const PLUS_ONE = "PLUS_ONE"; // export 안해도 됨
const MINUS_ONE = "MINUS_ONE"; // 지금은 type 밖에 없지만, 아래처럼 함수로 여러 값을 보낼 수 있게 된다.
// action creater : action value를 리턴
export const plusOne = () => { // App 에서 쓰기 위해 export
return {
type: PLUS_ONE,
};
};
export const minusOne = () => { // 마이너스도 추가
return {
type: MINUS_ONE,
};
};
const initialState = {
number: 0,
};
const counter = (state = initialState, action) => {
switch (action.type) {
case PLUS_ONE:
return { number: state.number + 1 };
case MINUS_ONE:
return { number: state.number - 1 };
default:
return state;
}
};
export default counter;
App.js
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
import { plusOne, minusOne } from "./redux/modules/counter"; {/*함수 import*/}
function App() {
const counter = useSelector((state) => {
return state.counter;
});
const dispatch = useDispatch();
return (
<>
<div>현재 카운트 : {counter.number}</div>
<button
onClick={() => {
dispatch(plusOne()); {/*함수의 리턴 값 보냄*/}
}}
>
+
</button>
<button
onClick={() => {
dispatch(minusOne());
}}
>
-
</button>
</>
);
}
export default App;
하드코딩 없이 값을 넘겨주는 중.. 🥲
'React' 카테고리의 다른 글
[React] React Router Dom(1) : 페이지 이동 & path 지정, Hooks, Layout & children (0) | 2024.01.25 |
---|---|
[React] Redux(2) : action 객체에 payload 를 넘겨보자, Ducks 패턴 (2) | 2024.01.25 |
[React] 최적화 & 리렌더링 막기(3) : useMemo, value 값 캐싱 (1) | 2024.01.24 |
[React] 최적화 & 리렌더링 막기(2) : useCallback, 함수 캐싱 (2) | 2024.01.24 |
[React] 최적화 & 리렌더링 막기(1) : React.memo, 자식 리렌더링 막기, 컴포넌트 캐싱 (0) | 2024.01.24 |