Redux 이해하기(2)

김하은·2022년 12월 18일
2

Project-Study

목록 보기
7/7
post-thumbnail

이해한 Redux 흐름의 원리를 바탕으로 예제를 한번 만들어 보았다.

🧡Redux 흐름

  1. 변경 이벤트가 발생되면 변경될 이벤트값이 action이 생성.
  2. 그 action 은 Dispatch 함수의 인자로 전달되고 reducer 를 통해 전역 상태 저장소 Store의 state 를 바꾼다.
    (이때 action은 현재(state, action)값을 reducer에 넘겨준다.)
  3. state 변경 후 -> dispatch가 subscribe 를 통해 render 함수를 호출 -> getState 로 state 값을 가지고 와 render 가 화면을 다시 그려준다.

💙결과) color 버튼 클릭시 나머지 박스 배경색이 해당 color로 변경


💜작성 코드

  1. 액션 타입, 액션 생성함수, 초기 상태 선언, 리듀서 선언
    📁module/color.js
//📍액션 타입 만들기
// Ducks 패턴을 따를땐 액션의 이름에 접두사를 넣어주세요.
// 이렇게 하면 다른 모듈과 액션 이름이 중복되는 것을 방지 할 수 있습니다.
export const CHANGE_COLOR = 'color/CHANGE_COLOR';

//📍액션 생성함수 만들기
//액션 생성함수를 만들고 export 키워드를 사용해서 내보내주세요.
export const red = () => ({ type: CHANGE_COLOR, color:'red'});
export const blue = () => ({ type: CHANGE_COLOR, color:'blue'});
export const green= () => ({ type: CHANGE_COLOR, color:'green'});

//📍초기 상태 선언
const initialState = {
  color: 'yellow'
};

//📍리듀서 선언
//리듀서는 export default 로 내보내주세요.
export default function colorReducer(state = initialState, action){
  //console.log(action, state)
  if(state === undefined){
    return {color:'yellow'}
  }
  if(action.type === CHANGE_COLOR){
    //console.log(action.color);
    return {
      ...state,
      color : action.color
    };
  }else{
    return state;
  }
};

🚩 코드 설명

-> 액션 생성 함수를 만든다. action이 일어나면 action 에 생성 함수가 호출. 그러면 타입이 CHANGE_COLOR, 라는 액션을 반환후
액션 생성 함수가 값을 반황하면, 리듀서로 지정한 (state, action)호출.
만약 현재 state 값이 없을시 default 값이 yellow 이고,
action.type 이 === CHANGE_COLOR 이면, return 값으로
...state,
color : action.color 액션에있는 color 값이 반환된다.
그후 store 에 저장.


  1. 📁module/reducer.js
import { combineReducers } from "redux";
import colorReducer from "./color";

const rootReducer = combineReducers({
    colorReducer
})

export default rootReducer;

🚩 코드 설명

-> colorReducer가 return하면 이 리턴된 값을 스토어(Store)에 저장해야 한다. modules/reducer.js에서 쓰인 📍combineReducers()함수 는 여러 가지 리듀서를 한 가지로 합쳐주는 함수인데, 프로젝트에서는 여러 reducer 를 사용하기 때문에 rootReducer라고 리듀서를 따로 지정해서 관리 한다.


  1. 📁index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import  {legacy_createStore as createStore} from 'redux'
import { Provider } from 'react-redux';
import rootReducer from './modules/reducer';

const store = createStore(rootReducer);

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

🚩코드 설명

-> index.js 에 store 을 만들어주고 생성한다. 스토어에 리듀서를 저장하기 위해 < APP > 에 < Provider > 을 감싸주고 Store를 등록해준다.
이렇게 하면 App 컴포넌트 하위에 있는 컴포넌트 들은 프로바이더에 등록된 스토어에서 저장된 값들을 자유롭게 사용할 수 있게 된다.


  1. 📁component/color.js
import React from 'react';
import styled from 'styled-components';

const Color = ({ color, onRed, onBlue, onGreen}) => { 

return(
  <Container>
    <h1>{color}:현재color값</h1>
    <Inner>
    <Redbox classname='red' style={{backgroundColor: color}}>RED
    <button onClick={onRed}>RED</button>
    </Redbox>

    <Bluebox classname='blue' style={{backgroundColor: color}}>BLUE
    <button onClick={onBlue}>BLUE</button>
    </Bluebox>

    <Greenbox classname='green' style={{backgroundColor: color}}>GREEN
    <button onClick={onGreen}>GREEN</button>
    </Greenbox>
    </Inner>
  </Container>
)
};
export default Color;

const Container = styled.div`
  width: 800px;
  height: 800px;
  //background-color: aliceblue;
  position: relative;
`
const Inner = styled.div`
  width: 600px;
  height: 800px;
  //background-color: pink;

`
const Redbox = styled.div`
  width: 200px;
  height: 200px;
  border: solid black;
 
`
const Bluebox = styled.div`
  width: 200px;
  height: 200px;
  border: solid black;
`
const Greenbox = styled.div`
   width: 200px;
  height: 200px;
  border: solid black;
`

🚩코드 설명

-> red, blue, green 박스와 해당 색상의 button 을 넣고 onClick 이벤트 함수를 생성한다.
이벤트 함수는 props 로 📁action/container.js 에서 받아온다.
받아온 {color}를 style={{backgroundColor: color}} 로 전달해
박스 배경색이 해당 color 값으로 바뀌게 한다.


  1. 📁action/container.js
import React from 'react';
import {useSelector, useDispatch } from 'react-redux';
import Color from '../components/color';
import { red, green, blue } from '../modules/color';

function ContainerAction() {
  // useSelector는 리덕스 스토어의 상태를 조회하는 Hook입니다.
  // state의 값은 store.getState() 함수를 호출했을 때 나타나는 결과물과 동일합니다.
 const { color } = useSelector(state => ({
    color: state.colorReducer.color
  }));

  // useDispatch 는 리덕스 스토어의 dispatch 를 함수에서 사용 할 수 있게 해주는 Hook 입니다.
  const dispatch = useDispatch();
  // 각 액션들을 디스패치하는 함수들을 만드세요
  const onRed = () => dispatch(red());
  const onGreen = () => dispatch(green());
  const onBlue = () => dispatch(blue());

  return (
    <Color
      // 상태와
      // 액션을 디스패치 하는 함수들을 props로 넣어줍니다.
      color={color}
      onRed={onRed}
      onGreen={onGreen}
      onBlue={onBlue}
    />
  );
};
export default ContainerAction;

🚩코드 설명

->
1) useSelector()를 통해 store 의 상태를 조회하고 , 일치하는 조건 값을 반환한다. 반환후 props 를 통하며 전달

2) 액션을 디스패치 하는 함수들을 만들고 , 디스패치에 dispatch(blue()) 📁component/color.js 에 선언해둔 컬러 값을 넣어준다. 어떤 이벤트가 생겼을시 이 디스패치가 호출되면서 안에 있는 컬러의 action 이 생성 된다.

3) return (
< Color > 로 액션을 디스패치 하는 함수들을 props 로 전달한다.


  1. 📁App.js
import React from 'react';
import './App.css';
import ContainerAction from './action/containerAction';

function App () {
  return(
    <div className='App'>
      <ContainerAction/>
    </div>
  )
};

export default App;

🚩코드 설명

-> app.js 에 컴포넌트를 선언해 준다.


🔥오류 Point

-> 📁action/container.js 에 이런식으로 코드를 만들었을때
아래와 같이 클릭시 버튼에 해당되는 값들은 cosole.log 창으로
출력이 되지만, color 값들이 입혀지지는 않았다.

import React from 'react';
import { useDispatch } from 'react-redux';
import Color from '../components/color';
import { red, green, blue } from '../modules/color';

function ContainerAction() {
  
  // useDispatch 는 리덕스 스토어의 dispatch 를 함수에서 사용 할 수 있게 해주는 Hook 입니다.
  const dispatch = useDispatch();
  // 각 액션들을 디스패치하는 함수들을 만드세요
  const onRed = () => dispatch(red());
  const onGreen = () => dispatch(green());
  const onBlue = () => dispatch(blue());

  return (
    <Color
      onRed={onRed}
      onGreen={onGreen}
      onBlue={onBlue}
    />
  );
}

export default ContainerAction;

-> 생각해보니 color 변화값이 일어나지만, 적용이 되지 않는다면
상태변화가 일어난후에 새로운 변경 state값으로 render 되지 않아서 일어나는 오류인것 같았다.

const { color } = useSelector(state => ({
    color: state.colorReducer.color
  }));

따라 useSelector 로 state 로 조건에 맞는 colorReducer.color 를 조회한후 { color } 변수에 담아 props 로 넘겨 주었더니

return (
    <Color
	  color={color}
      onRed={onRed}
      onGreen={onGreen}
      onBlue={onBlue}
    />

원하는 결과 값이 나왔다.
위에 결과를 보면
맨 상단에는 변경된 color 값들의 이름이 나오고 있고,
변경 state 값이 없을땐 기본 default 값인 yellow 컬러가 나타난다.
버튼을 누르면 3개의 박스가 동시에 버튼에 써진 color 값대로 변경 되는것을 볼수 있다.


후기🍀
redux 라는 상태관리 라이브러리 = 어렵다, 이해할께 많다😫
라고 들어서 인지 제대로 알기도 전에 조금 공부하기 두려움 마음이 있었다. 하지만, 프로젝트를 하면서 코드의 가독성을 더 좋게 하기 위해선
상태관리 가 필수 였고, 몸소 느낀 이상 redux 에대해 정확하게 공부 해 보자 하는 마음으로 시작했다.
redux 의 흐름을 이해하기 까지 꽤 걸렸지만, 이제 라도 redux 라는 라이브러리를 어떻게 사용하고 어떤식으로 흘러가는지 이해할수 있어서 홀가분하다.
이해한 것을 바탕으로 프로젝트에 사용해 코드의 가독성을 높이도록 해야겠다.

profile
꾸준함을 이기는것은 없다

0개의 댓글