일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |
- 의사클래스
- 부트캠프 #코딩 #개발일지 #프론트엔드 #CSS #TIL
- 부트캠프
- 부트캠프 #스파르타코딩클럽 #개발일지# #TIL #Javascript #confirm #location.href
- 부트캠프 #개발일지 #TIL #Position #위치
- 깃허브오류
- 리액트
- Til
- 부트캠프 #개발일지 #TIL #CSS속성 #float #clear
- appendChild
- 부트캠프 #스파르타코딩클럽 #개발일지# #html
- JS예제
- textContent
- 템플릿스트링
- 부트캠프 #개발일지 #TIL #FlexboxFroggy #displayflex #flexbox
- CSS
- ㅜㄹㄹ
- 부트캠프 #CSS #개발일지 #TIL
- 결합선택자
- 부트캠프 #CSS #개발일지 #TIL #박스모델
- useEffect
- React
- 개발일지 #TIL #프론트엔드 #HTML
- js
- 부트캠프 #개발일지 #TIL #그리드 #CSS
- querySelector
- useState
- 특성선택자
- 개발일지
- 알고리즘
- Today
- Total
나의 개발일지
[Redux] Redux를 사용하는 이유 / Redux 실행 과정 이해하기 /Counter 만들기 본문
Redux가 필요한 이유
useState의 불편함
- 반드시 부모-자식 관계가 형성돼있어야 한다
- 조부모에서 손자 컴포넌트로 보낼 시 반드시 부모 컴포넌트를 거쳐야 한다
- 자식--> 부모로 보낼 수 없다
하지만 redux를 쓰게 된다면 중앙 state 관리소에서 생성된 Global state에서 불러와서
사용할 수 있다! 어느 특정 컴포넌트에 종속되어 있지 않다
유지보수성이 좋아진다.
리덕스 패키지 설치
git bash에 yarn add redux react-redux 입력 후 설치 --> package.json 에서 확인 --> 폴더 생성
counter.js
// 초기 상태값(state)
// const [number, setNumber] = useState(0)
const initialState = {
number: 0,
};
// 리듀서 : 'state에 변화를 일으키는' 함수
// state를 action의 type에 따라 변경하는 함수
// input : state와 action 두 가지의 인자
// action에는 type과 payload가 있다
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
export default counter;
Action : { type, payload } 형태의 객체
- 리듀서 함수에게 전달되는 인자
- 리듀서에게 요구할 상태변경 작업에 대한 정의를 나타내는 객체
( 상태 변경 요청서 )
configStore.js
Reducer : state 변경 함수
- 매개 변수로 기존 상태와 액션 객체를 받음
- 상태 변경 후 최신 상태를 Store에 제공(리턴)
// 중앙 데이터 관리소(store)를 설정하는 부분
import { createStore } from "redux";
import { combineReducers } from "redux";
const rootReducer = combineReducers({
//리듀스를 묶어놓는 곳
counter : counter,
});
const store = createStore(rootReducer);
export default store;
createStore()
리덕스의 가장 핵심이 되는 스토어를 만드는 메소드(함수)
리덕스는 단일 스토어이기 때문에 createStore를 단 한 번만 호출!
combineReducers()
리덕스는 action -> dispatch -> reducer 순으로 동작한다
app이 복잡해지게 되면 reducer 부분을 여러 파일로 나눠야 하는데
이 때 combineReducers는 여러 개의 독립적인 reducer의 반환 값을 하나의 객체 상태로 만들어준다
export default store;
default 를 해놨기 때문에 index.js에서 import 할 때 { } 필요없다
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import store from "./redux/config/configStore";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
App을 <Provider>로 감싸주고, configStore에서 export default 한 store를 넣어준다
** 너무 세세하게 이해하려고 하지 않기 **
App.jsx
import "./App.css";
function App() {
// 여기에서 store에 접근하여, counter의 값을 읽어오고 싶다!
// useSelector 사용
const data = useSelector((state)=>{
return state;
})
console.log('data', data)
return <div>Redux!</div>;
}
export default App;
컴포넌트에서 스토어를 직접 조회하기 --> useSelector()
( ) 안에는 함수
return 하여 console.log로 확인하기
만약 counter만 확인하고 싶다면?
const counter = useSelector((state) => {
return state.counter;
});
console.log("counter", counter.number);
Counter 만들어보기
우선 만들기 전,
우리는 dispatch가 무엇인지 알 필요가 있다
dispatch는
예를 들어 onClick이 발생하면 action 객체를 가지고 store에 던져주는 역할을 한다 (전달자 함수)
dispatch라는 함수에는 액션을 파라미터로 전달한다(dispatch(action))
그리고 type과 payload를 가지고 있다
+1 기능 구현해보기
1. UI를 만든다
2. 리듀서에게 number + 1을 하라는 명령을 보낸다
그 명령이 바로 action 객체
const counter = (state = initialState, action) => {
console.log(state);
switch (action.type) {
case "PLUS_ONE":
return {
number: state.number + 1,
};
default:
return state;
}
};
export default counter;
3. useDispatch 훅 만들기
4. onClick 이벤트 추가
마우스를 클릭했을 때 dispatch(action)이 실행되고, ( )안에 있는 액션객체가 리듀서로 전달된다.
++) 만약 "PLUS_ONE"이 수백개의 파일에서 쓰여지고,
수정해야 할 일이 있다면 하나하나 수정하기란 번거롭다
그래서 변수에 저장해서 사용하면 휴먼에러를 줄일 수 있다
다른 파일에서도 쓰기 위해 export , import 필수
더 간단하게 구현 ▼
action creator :액션 객체도 변수 선언해주기
dispatch 안에 있는 객체를 counter.js 에서 만들어준다
(App컴포넌트에서 사용해야 하니까 꼭 export 해주기)
액션 객체 변수 선언
dispatch안에서 만든 함수 호출(return 값을 반환한다)
입력한 숫자만큼 더해지거나 빼주는 Counter 만들기 (payload)
const [number, setNumber] = useState(0);
div>현재 카운트 : {counter.number}</div>
<input
type="number"
value={number}
onChange={(event) => {
setNumber(event.target.value);
}}
></input>
//number가 렌더링 될 때마다 실행된다!!
useEffect(() => {
console.log("number", number);
}, [number]);
input 태그를 관리하는 state를 만들기
실제 렌더링될 때마다 state 값이 변하는지 확인하기 위해
useEffect를 사용하여 console.log에 찍어보았다
배열 [number] 가 실행될 때마다 state 값이 변경된다
counter.js
const PLUS_N = "PLUS_N";
const MINUS_N = "MINUS_N";
// payload를 인자로
export const plus_n = (payload) => {
return {
type: PLUS_N,
payload,
};
};
//payload 만큼 숫자 변화
export const minus_n = (payload) => {
return {
type: MINUS_N,
payload,
};
};
const counter = (state = initialState, action) => {
console.log(state);
switch (action.type) {
case PLUS_ONE:
return {
number: state.number + 1,
};
case MINUS_ONE:
return {
number: state.number - 1,
};
// 현재 state 값에서 + payload 값만큼 더해주기
case PLUS_N:
return {
number: state.number + action.payload,
};
case MINUS_N:
return {
number: state.number - action.payload,
};
default:
return state;
}
};
App.jsx
import { minus_n } from "./redux/modules/counter";
import { plus_n } from "./redux/modules/counter";
return (
<>
<div>현재 카운트 : {counter.number}</div>
<input
type="number"
value={number}
onChange={(event) => {
// + --> 자동으로 문자열에서 숫자로 변환 ***
setNumber(+event.target.value);
}}
></input>
<br />
<button
onClick={() => {
// dispatch({ type: PLUS_ONE });
// 함수 호출 시, payload 인자값도 같이
// 인자값은 바뀌는 state랑 연결돼있다
dispatch(plus_n(number));
}}
>
+
</button>
<button
onClick={() => {
// dispatch({ type: MINUS_ONE });
// dispatch(minus_one());
dispatch(minus_n(number));
}}
>
-
</button>
</>
);
'React > Redux' 카테고리의 다른 글
[React] Redux-Toolkit 설치 / counter app / TodoList (1) | 2023.12.23 |
---|---|
[React] Redux로 TodoList 만들기 (0) | 2023.11.28 |