Redux basic 리덕스

lim1313·2021년 9월 17일
0

TILPLUS

목록 보기
23/40
post-custom-banner

📌Redux의 구성 요소

1. store

: 애플리케이션의 상태를 관리하고, .getState(), .dispach(), .subscribe() 같은 메서드를 제공
: React 컴포넌트에 분산되어 있는 상태 객체와 달리 스토어는 하나만 존재합니다. 스토어는 애플리케이션에 상태를 제공하며 상태가 업데이트 되면 뷰(UI)가 다시 그려진다.

2. action

: "상태 변경을 설명하는 정보"를 스토어로 보내는 JavaScript 객체로 Redux에 알려(dispatch) 변화를 이끌어낸다.

3. getState

: store 안에 들어있는 상태를 조회
: getState를 통해 state값에 접근

4. render

: state값을 참조하여 ui를 생성
: state값을 직접 변경해서는 안된다.
-> {...state}와 같이 새로운 객체를 생성!

5. dispatch

: dispatch는 reducer를 호출하여 state 값을 바꾼다.
: reducer에 (state, action)라는 두가지 값을 전달
: 현재의 store의 state값 & dispatch를 통해 보낸 값(action)

6. reducer

: 애플리케이션 상태를 교체하는 함수
: dispatch에 의해 reducer함수 호출
: state를 입력값으로 받고 action를 참조하여 새로운 state값을 리턴
: reducer에서 return해주는 값이 state의 새로운 값이 된다.

7. subscribe

: 상태 변경을 구독(subscribe, 감지) 하여, 상태가 업데이트 되면 등록된 리스너(listener)를 실행
: render함수를 subscribe에 등록하여 state값이 바꿀 때마다 render함수가 호출되어 ui가 변경된다.


📌Redux 사용

📎Redux Hook

useSelector()

리덕스 스토어의 상태를 조회하는 Hook

useSelector를 사용해서 리덕스 스토어의 상태를 조회 할 때, 만약 상태가 바뀌지 않았으면 리렌더링하지 않는다.

아래와 같이 작성한다면 매번 렌더링 될 때마다 새로운 객체를 만드는 것이기 때문에, 불필요한 렌더링이 발생할 수 있다.

const { subscribers, view } = useSelector(state => ({
    subscribers: state.subscribers,
    view state.view
  }));
  
const state = useSelector((state) => state.itemReducer);
const { cartItems, items } = state;

이를 최적화하기 위한 방법은 두가지가 있다.

  1. useSelector를 여러번 사용하는 것이다.
const number = useSelector(state => state.counter.number);
const diff = useSelector(state => state.counter.diff);
  1. react-redux의 shallowEqual 함수를 useSelector의 두번째 인자로 전달해주는 것.
 const { number, diff } = useSelector(
    state => ({
      number: state.counter.number,
      diff: state.counter.diff
    }),
    shallowEqual
  );

useDispatch()

리덕스 스토어의 dispatch 를 함수에서 사용 할 수 있게 해주는 Hook

const dispatch = useDispatch();

 const dispatch = useDispatch();

return(
 <button onClick={() => dispatch(addSubscriber())}>UPUP</button>
)

📌Redux 모듈화

type.js

export const ADD_NUMBER = 'ADD_NUMBER';
export const ADD_NUMBER_LATER = 'ADD_NUMBER_LATER';

actions.js

import { ADD_NUMBER } from './type';
import { ADD_NUMBER_LATER } from './type';

export const addNumber = () => {
  return {
    type: ADD_NUMBER,
  };
};

export const addNumberLater = () => {
  return (dispatch, getState) => {
    setTimeout(() => dispatch(addLater()), 1000);
  };
};

const addLater = () => {
  return {
    type: ADD_NUMBER_LATER,
  };
};

reducer.js

import { ADD_NUMBER, ADD_NUMBER_LATER } from './type';

const initialState = {
  count: 330,
};

const addNumberReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_NUMBER:
      return { ...state, count: state.count + 1 };
    //! default를 꼭 설정해줘야 한다!!
    case ADD_NUMBER_LATER:
      return { ...state, count: state.count + 3 };
    default:
      return state;
  }
};

export default addNumberReducer;

rootReducer.js

import addMessageReducer from './message/reducer';
import addNumberReducer from './number/reducer';
import { combineReducers } from 'redux';

const rootReducer = combineReducers({
  number: addNumberReducer,
  message: addMessageReducer,
});

export default rootReducer;

store.js

import { createStore, applyMiddleware } from 'redux';
import addNumberReducer from './number/reducer';
import rootReducer from './rootReducer';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';

const middeWare = [thunk];

const store = createStore(
  rootReducer,
  composeWithDevTools(applyMiddleware(...middeWare))
);

export default store;

App.js

import './App.css';
import Message from './components/Message';
import Number from './components/Number';
import { Provider } from 'react-redux';
import store from './redux/store';

function App() {
  return (
    <Provider store={store}>
      <Number />
      <Message />
    </Provider>
  );
}

export default App;

index.js

styled component, redux 등 같이 사용했을

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';

import GlobalStyle from './styled/globalStyled';
import { ThemeProvider } from 'styled-components';
import theme from './styled/theme';

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <GlobalStyle />
        <App />
      </ThemeProvider>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
profile
start coding
post-custom-banner

0개의 댓글