Notice
Recent Posts
Recent Comments
«   2024/06   »
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
Tags more
Archives
Today
Total
관리 메뉴

HYEWON JUNG의 개발일지

Redux 본문

React

Redux

혜won 2023. 11. 10. 08:30

redux는 상태 관리 라이브러리라고 하는데 redux는 왜 필요한가. 

장점이 3가지가 있는데 

1. 리덕스를 사용하면State를 공유하고자 할때 부-모 관계가 아니여도 된다

2. 중간에 의미없이 컴포넌트를 거치지 않아도 된다.

3. 자식 컴포넌트에서 만든 State를 부모 컴포넌트에서도 사용할 수 있게 된다.

4. 중앙 state관리소를 가지고 있다.(접근 및 제어를 할 수있다.)

 

redux 사용 방법 

새 프로그램 src폴더 안에 redux란 파일을 만든 뒤  , 그 안에 modules와 config폴더를 만들어준다. config파일 안에 configStore이란 js파일까지 만들어준다. 

redux : 리덕스 관련 코드를 모두 넣을 것

config: 리덕스 설정 관련 파일 전부

configStore : 중앙 state관리소 -> 설정코드

modules : state의 그룹

 

만든 파일에  차례로 넣어준다.

  • conifgStore.js에 설정코드 넣기  state 만들기
import { createStore} from "redux";  		//필요한 두가지 api import
import { combineReducers } from "redux";	//reducer를 하나로 묶는 역할

const rootReducer = combineReducers({reducer들 넣을겨}); //reducer를 모아서 하나로 만든 기본 reducer
const store = createStore(rootReducer);		//store 생성 인자로 reducer의 인자가 들어가야함

export default store;
  • index.js에 App 컴포넌트를 provider 안에 넣고 provider에 import한 store를 넣기
import { Provider } from 'react-redux';
import  store  from './redux/config/configStore';

root.render(
  <Provider store={store}>  //App이라는 컴포넌트가 provider의 지배권 안으로 들어감
    <App />
  </Provider>		
    
  
);

 

provider에 store를 넣어주면 App컴포넌트 하부에 속하는 모든 컴포넌트에서 store를 사용할 수 있다.

  • module 만들기(예제 counter.js)
    -  state의 초기 상태값 필요 
const initialState = {
    number: 0
};

===

const [number, setNumber] = useState(0)

   - reducer 생성  

const counter = (state = initialState, action) => {
    switch (action.type) {
      
        default:
            return state;
    }
}
export default counter; //내보내기 잊으면 안됨

reducer는 state의 초기값을 나태내주는 것과 , action이 들어간다. 그래서 reducer가 가지고 있는 type에 따라 state의 변경이 일어난다. 

state = initialState 는 state의 초기값은 initialState 즉 {number:0}이라고 말해주는 것이고

action은 state를 어떻게 변화를 실행하는 객체인데 type과 value를 가지고 있다.

  • combineReducer에 생성한 reducer넣기 
import counter from "../modules/counter"; //가져오기 잊으면 안됨

const rootReducer = combineReducers({
    counter,
});

이제 본격적으로 counte라는 reducer가 담긴 store를  App에서 사용할 수 있는 상태가 된 것 이다.

  • store 사용하기 with . Redux hook(useSelector)
const counter = useSelector((state)=>{
  return state.counter;
})

return을 state가 아닌 state.counter로 하는 이유는 현재 상태의 state는 reducer 객체의 counter에 접근 하는 것이니 객체에 접근하는 것처럼 counter에 접근해야한다.

  • UI만들기

useSelector를 통해서 값을 가져왔고 UI를 만들어서 event가 있으면 카운트가 될 수있는 로직을 작성해보자

    <>
      <div>현재 카운트 :{counter.number}</div>
      <button>+1</button>
      <button}>-1</button>
    </>

useState라면 setState를 이용해서 카운트를 변경하겠지만 redux에선 store에 접근해야 하기 때문에 redux의 작동 방식을 봐보자

UI에서 클릭이벤트를 주면 eventhandle에서 dispatch가 action객체를 들고 store에 전달해주면 reducer가 새로운 state를 내보내 리렌더링된다.

 

그렇다면 카운터 에서는 number+1이 되는 로직이 있어어야하는데 위에서 redux에서 state의 변경은 reducer가 지정한 type에 따라 달라진다고 했었는데 아직은 type에 아무것도 나두지 않았기 때문에 counter 모듈에서  action에 타입을 추가해줘야한다. 

 

switch문에 case로 +1 type과 -1type을 추가해준다 .

위에 초기 state값인 number : 0  에 맞춰서  number =  현재 state의 number +1을 해주는 것이다.

  • action type 에 추가하기 
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
            }
        default:
            return state;
    }
}

그리고 App컴포넌트로 돌아와서 reducer에 전달해줄 dispatch를 만들어줘야합니다.

  • js영역에 dispatch 선언해주기
const dispatch = useDispatch();
  • dispatch 이용해서 action객체 보내기
    <>
      <div>졸림 지수 :{counter.number}</div>
      <button onClick={()=>{
        dispatch({
          type:"PLUS_ONE"
        })
      }}>+1</button>
      <button onClick={()=>{
        dispatch({
          type:"MINUS_ONE"
        })
      }}>-1</button>
    </>

onclick={()=>{dispatch({type: 타입이름})}} 이렇게 온클릭의 로직으로 디스패치가 들어가고 디스패치에 객체로 action이 들어간다.

  • 마무리

지금까지 만든 counter앱을 리팩토링 할 거다.

1. type의 이름 바꾸기 => 팀프로젝트 시 확실한 구분을 위해

2. 이름을 문자열 말고 상수로 선언하기 => 휴먼 에러 줄이기 = action value

3. App컴포넌트에 dispatch가 넘겨줄 action객체를 만들어줄 함수를 만들어서 export하자 => action Creator

//action value
export const PLUS_ONE = "counter/PLUS_ONE"
export const MINUS_ONE = "counter/MINUS_ONE"
//action Creator = action value를 반환 하는 함수
export const plusOne =()=>{
    return{
        type: PLUS_ONE,
    }
}

export const MinusOne =()=>{
    return{
        type:MINUS_ONE
    }
}

 

이렇게 수정해주면 된다. action creator는 단지 객체를 반환할 뿐인 함수라고 생각하면된다.

 

근데  왜 action은 객체인데 객체 자체를 선언하지 않고 객체를 반환하는 함수를 사용해야하는 걸까? 

=> 실제로 action creator를 하는 것이 아닌 action type 자체를 넘겨주어도 문제없이 실행되는 것을 볼 수 있었다. 

 

단순하게는 redux팀이 지향하는 방식이기도 하고 humanError를 줄일 수 있기도하다는데 (변수 선언만 해도 에러가 바로 잡히긴 하는데.. )

'React' 카테고리의 다른 글

children 활용하기  (0) 2023.11.13
redux payload, Ducks  (1) 2023.11.12
component LifeCycle 생명주기  (1) 2023.11.09
React Hooks useContext, reactMemo, useCallback, useMemo  (1) 2023.11.09
useState, useEffect, useRef  (0) 2023.11.08