본문 바로가기

🌼 TIL

🌞 2/2 내배캠 React 68일차 [React - Redux]

Next.js를 배우다가 Redux를 활용하여 CRUD를 구현하기 위해 Redux를 다시 복습해보기로 정했다.

 

Redux -react redux

React에서 조금 더 쉽게 쓸 수 있는 도구이다.

요즘은 순수 react를 쓰는 것은 없다.

[ Let’s get it ]

순수 기존 리엑트의 개발방법 및 한계

  • 컴포넌트 폴더마다 각 파일들을 분리했고, 각 폴더마다 style.css를 파일로 만들어서 넣어주는 형식을 채택했음
  • index.html이 public 폴더에 위치하고 있다.
  • index.html 파일의 역할은 root라는 div를 가져오는 것이다.
  • index.js의 파일에는 document.getElementById에서 돔요소의 root라는 id를 가진 요소를 선택하게 되어있다.
  •  
  • root에는 가장 깊은 곳에 App이라는 컴포넌트를 가지고 있다.→
    1. index.html을 가져와서
    2. id가 root인 div를 찾는다
    3. root에서 App.jsx 를 불러 이곳에서 개발을 하게된다 <- 여기가 개발하는 Playground!!
      1. 여기선 State와 Props를 가지고 개발을 해 나갔다 !!
      2. 때론 setState를 이용해서 제어할 수 있는 과정을 만들어 줬다.
    reactct의 가장 기본적인 형태
    1. App.jsx에서는 하위 컴포넌트를 호출하고, props를 내려준다(ex . <TodoList todos={todos}/>)
    2. Todolist라는 하위 컴포넌트 에서는 props를 받는다 (ex. function TodoList({todos}))
    3. retunr문 안에서 개발
    4. 여기서 하위컴포넌트에 그 하위컴포넌트로 넘겨주기 위해 props로 사용되는 것들이 있다.
    5. 그 props들은 하위 컴포넌트에 쓰이지 않더라도 넘겨주기 위해 작성되어야 한다.(prop drilling)
    6. 이렇게 계속 넘겨주다가 하나라도 끊키면 props를 쓸 수 없다.
    → 만약 props로 하위 컴포넌트로 내려줘야하는 일이 100개라면 99번을 내려줘야하기 때문에 관리하기 힘들다 그리고 중간에 props에 name이 바뀌거나 수정사항이 생긴다면…🤬
  • App = App.jsx / App.js
  • const root = ReactDOM.createRoot(document.getElementById("root"))
  • root는 src 폴더의 index.js 파일에 위치한다.
  • index.html은 모든 프로젝트중 가장 먼저 불러오는 파일이다.
  • 컴포넌트 폴더마다 각 파일들을 분리했고, 각 폴더마다 style.css를 파일로 만들어서 넣어주는 형식을 채택했음
```jsx
const root = ReactDOM.createRoot(document.getElementById("root"))
```
const root = ReactDOM.createRoot(document.getElementById("root"))
const root = ReactDOM.createRoot(document.getElementById("root"))
const root = ReactDOM.createRoot(document.getElementById("root"))

Redux가 필요한 이유

  1. 기존 순수 리엑트는 prop drilling을 일일이 해줘야 하기 때문에 상태관리가 힘들다
  2. 손쉽게 상태관리하는 도구가 필요하다.

기존의 수없이 많은 곳에서 참조하고, 관리됐던(수정됐던) state를 한곳 = **(Store/저장소)**으로 몰아넣게 된다.

state에 변경되는 값들이 너무 많다 보니 이것들을 관리하자 그것을 reducer라는 곳에 state들을 다 넣어놓는다

Store 안에는 State와 Reducer가 들어가 있다. store안에 dispatch(처리방법)로 넣어 놓을 수 있다.

(dispatch안에 event handler가(action이라는 객체) 담겨있다)

→ 모든 컴포넌트를 다 파지 않아도 된다.

redux : 전역 state → store에 있는 놈들

react : 지역 컴포넌트 state → 컴포넌트 내부에 있는 state

configStore.js

// 2. combineReducer()
// 리덕스는 action -> dispatch -> reducer 순으로 동작한다고 한다. 
// 이때 애플리케이션이 복잡해지게 되면 reducer 부분을 여러 개로 나눠야 하는 combineRedcuers은
// 여러 개의 독립적인 reduce의 반환 값을 하나의 상태로 나타낸다.

// 1. 리듀서를 만든다.
const rootReducer = combineReducers({
	counter,
});

// 2. 만든 리듀서를 통해 store를 생성한다.
const store = createStore(rootReducer);

// 3. 생성한 sotre를 export 한다.
export default store;

store라는 것을 configure에서 만들어서 밖으로 내보낸다.

state와 reduce가 필요한 놈들이 이것을 가져와서 쓸 것이다.

modules / counter.js (reducer를 만든 부분) 여기서 counter가 리듀서이다.

modules안에 reducer를 만들어 줘야한다.

// Action Value = type,payload의 결합을 의미함 -> 무슨일을 할지를 결정하는 것
// 상수라서 대문자로 입력한다. 이름이 딱 알아보기 쉬워야 한다.
// action에서는 뭘 할지를 적어놓기 때문에 중요하다.
const ADD_NUMBER = "ADD_NUMBER";
const REMOVE_NUMBER = "REMOVE_NUMBER";

// Action Creator -> reducer에 들어가 있는 놈들
// action을 가진다 action = type과 payload를 가지고 있다.
// action을 일으키는 놈들 
// creator를 만들어 놓은 것 (addNumber) -> 이걸 UI(컴포넌트)들이 가져다가 쓴다.
export const addNumber = (payload) => {
	return {
		type: ADD_NUMBER,
		payload,
	};
 };

export const removeNumber = (payload) => {
	return {
		type : ADD_NUMBER.
		payload,
	};
 };

// Initial State
const initialState = {
	number: 0,
}

// Reducer -> state와 initial 을 가진다.
// action의 type에 따라서 case 8를 결정을 하고, 어떠한 state를 내보낼지 return문에서 적어놨다.
const counter = (state = initialState, action) => {
	switch (action.type) {
		case ADD_NUMBER : {
			return {
				number: state.number + action.payload,
			);
		}
	 case REMOVE_NUMBER : {
			return {
				number: state.number - action.payload,
			);
		}
	default: 
		return state;
	}
};

// export 
export default counter;

  • 예) Account reducer 만들기 입출금 기능 만들기
    // ex) 입금 출금 만들기
    //Action value만들기
    
    const DEPOSIT_DOLLAR = "DEPOSIT_DOLLAR";
    const WITHDRAW_DOLLAR = "WITHDRAW_DOLLAR";
    
    // action을 create 할수 있느 Action Creator 만들기
    export const depositDollar = (payload) => {
      return {
        type: DEPOSIT_DOLLAR,
        payload: payload,
      };
    };
    
    export const withdrawDollar = (payload) => {
      return {
        type: WITHDRAW_DOLLAR,
        payload,
      };
    };
    
    const initialState = {
      balance: 0,
    };
    
    // Reducer 만들기
    const account = (state = initialState, action) => {
      switch (action.type) {
        // 입금
        case DEPOSIT_DOLLAR: {
          return {
            balance: state.balance + action.payload,
          };
        }
        // 출금
        case WITHDRAW_DOLLAR: {
          return {
            balance: state.balance - action.payload,
          };
        }
        default:
          return state;
      }
    };
    
    // default = 대표값
    export default account;
    
    → 만든 후
    // 1. 리듀서를 만든다.
    const rootReducer = combineReducers({
    	counter,
    	account 
    });
    
    → App.jsx에 UI에 띄울 수 있게 만들어 보기
  • 예)
  • configStore.js 에 rootReducer에 만들어 놓은 account reducer 추가해 준다(= combine 해준다).
  • modules에 account.js 파일을 만든다