DBILITY

react redux redux-toolkit 본문

front-end & ui/react

react redux redux-toolkit

DBILITY 2023. 4. 13. 17:47
반응형

내년쯤 다시 볼지 모르니 기록하자.

https://redux-toolkit.js.org/

 

Redux Toolkit | Redux Toolkit

The official, opinionated, batteries-included toolset for efficient Redux development

redux-toolkit.js.org

redux-toolkit으로 여러가지 해결(?)되었다고 한다.

npm install react-redux @reduxjs/toolkit

createSlice를 쓰면 name/reducer형태의 action.type을 자동으로 생성해 준다.

action의 reducer를 export,사용하는 콤포넌트에선 import 후 dispath하면 된다.

이전 방식 dispath({type:"action type",payload:"object"}) 형태가 아닌 dispatch(userDefinedReducer(object))로 하면 된다?

Couter에 더하기,빼기를 해본다. setState없이 직접 수정이 가능한 건 Immer.js때문이라고 한다.

store를 만든다

import {configureStore, createSlice, current} from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "counter",
  initialState: {value: 0},
  reducers: {
    plus(state, action) {
      console.log(current(state),state.value);
      state.value = state.value + action.payload.value
    },
    minus(state, action) {
      console.log(current(state),state.value);
      state.value = state.value - action.payload.value
    }
  }
})

export const {plus, minus} = counterSlice.actions;
export default configureStore({
  reducer: {
    couterState: counterSlice.reducer
  }
})

Counter콤포넌트를 만든다.

import React from 'react';
import styled from "styled-components";
import {useDispatch, useSelector} from "react-redux";
import {plus, minus} from "./store";


const DivCounter = styled.div`
  text-align: center;
`;
const ButtonCounter = styled.button`
  text-align: center;
  background: dodgerblue;
  border: none;
  color: white;
  border-radius: 5px;
  margin-left: 10px;
  padding: 4px 10px 5px 10px;
`;

function Counter() {
  const counter = useSelector(state => state.couterState);
  const dispatch = useDispatch();
  return (
    <DivCounter>
      {counter.value}
      <ButtonCounter onClick={() => dispatch(plus({value: 1}))}>+</ButtonCounter>
      <ButtonCounter onClick={() => dispatch(minus({value: 1}))}>-</ButtonCounter>
    </DivCounter>
  );
}

export default Counter;

root.render에 Provider를 설정한다.

import React from "react";
import ReactDOM from "react-dom/client";
import Counter from "./Counter";
import store from "./store";

import {Provider} from "react-redux";


const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(
  <Provider store={store}>
    <Counter/>
  </Provider>
);

실행화면
untitled.zip
0.06MB

reducer는 sync, 필요하다면 createAsyncThunk를 통해 비동기 액션을 만들고 createSlice안에 extraReducers에 처리한다.

typescript를 사용하려고 보니

store정의의 기본 형태가 다음과 같다.

const store = configureStore({
    reducer: {
        ...
    }
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export default store;

위 couter sample과 비슷하게 typescript로 변경했다.

import {configureStore, createSlice, current, PayloadAction} from "@reduxjs/toolkit";

export interface TypeState {
    value: number
}

const initialState: TypeState = {
    value: 0
}

const counterSlice = createSlice({
    name: 'counter',
    initialState: initialState,
    reducers: {
        plus: (state: TypeState, action: PayloadAction<TypeState>) => {
            console.log(current(state), state.value);
            state.value = state.value + action.payload.value
        },
        minus : (state: TypeState, action: PayloadAction<TypeState>) => {
            console.log(current(state), state.value);
            state.value = state.value - action.payload.value
        }
    }
});

export const {plus, minus} = counterSlice.actions;

const store = configureStore({
    reducer: {
        counter: counterSlice.reducer,
    }
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export default store;
import React, {JSX} from 'react';
import {plus, minus, RootState, AppDispatch} from "./store";
import {useDispatch, useSelector} from "react-redux";

const CounterComponent = (): JSX.Element => {

    const counter = useSelector((state: RootState) => state.counter);
    const dispatch = useDispatch<AppDispatch>();

    console.log(counter);
    return (
        <div>
            <label>counter</label>{` `}
            {counter.value}{` `}
            <button onClick={() => dispatch(plus({value: 1}))}>+</button>
            {` `}
            <button onClick={() => dispatch(minus({value: 1}))}>-</button>
        </div>
    );
}

export default CounterComponent;

 

반응형

'front-end & ui > react' 카테고리의 다른 글

react image src path  (0) 2023.06.09
react react-toastify  (0) 2023.06.09
react styled component  (0) 2023.04.12
react cors proxy  (0) 2023.03.09
react v18 UseTransition, useDeferredValue hook  (0) 2022.06.07
Comments