티스토리 뷰

프론트엔드/React

Redux

yyoujg 2022. 6. 4. 15:31

1) 상태관리 흐름

[상태관리 흐름도]

(1) 리덕스 Store를 Component에 연결한다.

(2) Component에서 상태 변화가 필요할 때 Action을 부른다.

(3) Reducer를 통해서 새로운 상태 값을 만들고

(4) 새 상태값을 Store에 저장한다.

(5) Component는 새로운 상태값을 받아온다.(props를 통해 받아오니까 다시 랜더링된다.)

 

2) Redux

리덕스는 상태관리 라이브러리이다. (전역 상태관리를 편하게 할 수 있다.)

(1) State

리덕스에서는 저장하고 있는 상태값("데이터"라고 생각해도된다.)를 state라고 부른다.

딕셔너리 형태({key}: value) 형태로 보관한다.

(2) Action

상태에 변화가 필요할 때(= 가지고 있는 데이터를 변경할 때) 발생하는 것.

// 액션은 객체이다. 이런 형태로 쓰인다. type은 이름같은 것으로 임의의 문자열을 넣는다.
{type: 'CHANGE_STATE', data: {...}}

(3)ActionCreator

액션 생성 함수라고도 부른다. 액션을 만들기 위해 사용한다.

//이름 그대로 함수이다.
const changeState = (new_data) => {
// 액션을 리턴한다. (액션 생성 함수)
	return {
		type: 'CHANGE_STATE',
		data: new_data
	}
}

(4) Reducer

리덕스에 저장된 상태(=데이터)를 변경하는 함수이다.

→ 액션 생성 함수를 부르고

 액션을 만들면

 리듀서가 현재 상태(=데이터)와 액션 객체를 받아서

 새로운 데이터를 만들고

 리턴해준다.

// 기본 상태값을 임의로 정해준다.
const initialState = {
	name: 'youjung'
}

function reducer(state = initialState, action) {
	switch(action.type){

		// action의 타입마다 케이스문을 걸어주면, 
		// 액션에 따라서 새로운 값을 돌려준다.
		case CHANGE_STATE: 
			return {name: 'youjung1'};

		default: 
			return false;
	}	
}

(5) Store

프로젝트에 리덕스를 적용하기 위해 만드는 것이다.

스토어에는 리듀서, 현재 애플리케이션 상태, 리덕스에서 값을 가져오고 액션을 호출하기 위한 몇 가지 내장 함수가 포함되어 있다. 생김새는 딕셔너리 혹은 json처럼 생겼다.

(6) dispatch

디스패치는 스토어의 내장함수로 액션을 발생 시키는 역할을 한다.

// 실제로는 이것보다 코드가 길지만, 
// 간단히 표현하자면 이런 식으로 우리가 발생시키고자 하는 액션을 파라미터로 넘겨서 사용한다.
dispatch(action);

3) 리덕스가 필요하지 않은 경우

1.페이지 간 공유할 데이터가 없는 경우

2.페이지 이동 시 리패칭이 잦게 일어날 경우

3.비즈니스 로직이 획일화되기 어려울 경우

 

Redux Toolkit

리덕스툴킷은 리덕스를 편히 쓰기 위해 리덕스 팀에서 만든 패키지이다.

리덕스를 사용하는데 유용한 패키지 도구 모음.

툴 킷을 쓰게 되면 액션타입, 액션 생성함수, 리듀서, 기초값을 하나 번에 묶어서 사용할 수 있다.

→ 보일러 플레이트가 많이 줄어든다.

 

4) store 만들기

(1) import 할 것부터 다 하기

import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createBrowserHistory } from "history";
import { connectRouter } from "connected-react-router";

import User from "./modules/user";

(2) root reducer 만들기

const rootReducer = combineReducers({
  user: User,
});

(3) 미들웨어 준비하기

const middlewares = [thunk];

// 지금이 어느 환경인지 알려준다. (개발환경, 프로덕션(배포)환경 ...)
const env = process.env.NODE_ENV;

// 개발환경에서는 로거라는 걸 하나만 더 써볼 것이다.
if (env === "development") {
  const { logger } = require("redux-logger");
  middlewares.push(logger);
}

(4) 크롬 확장 프로그램 redux devTools 사용 설정하기

(5) 미들웨어 묶기

const enhancer = composeEnhancers(
  applyMiddleware(...middlewares)
);

(6) 미들웨어와 루트 리듀서를 엮어서 스토어를 만든다.

let store = (initialStore) => createStore(rootReducer, enhancer);

export default store();

5) slice 만들기

(1) import하기

import { createAction, handleActions } from "redux-actions";
import { produce } from "immer";

(2) 필요한 액션 만들기

const SET_POST = "SET_POST";
const ADD_POST = "ADD_POST";

const setPost = createAction(SET_POST, (post_list) => ({post_list}));
const addPost = createAction(ADD_POST, (post) => ({post}));

(3) initialState 만들기

const initialState = {
    list: [],
}

// 게시글 하나에는 어떤 정보가 있어야 하는 지
const initialPost = {
  user_info: {
		id: 0,
    user_name: "mean0",
    user_profile: "https://mean0images.s3.ap-northeast-2.amazonaws.com/4.jpeg",
  },
  image_url: "https://mean0images.s3.ap-northeast-2.amazonaws.com/4.jpeg",
  contents: "고양이네요!",
  comment_cnt: 10,
  insert_dt: "2021-02-27 10:00:00",
};

(4) 리듀서 작성하기

// reducer
export default handleActions(
  {
      [SET_POST]: (state, action) => produce(state, (draft) => {
        
      }),

      [ADD_POST]: (state, action) => produce(state, (draft) => {
          
      })
  },
  initialState
);

(5) export 하기

// action creator export
const actionCreators = {
  setPost,
  addPost,
};

export { actionCreators };

6) redux hook - 데이터 구독하기

// pages/PostList.js
...
import {useSelector} from "react-redux";
...
const PostList = (props) => {
	const post_list = useSelector((state) => state.post.list);
...

7) redux hook - 데이터 수정하기

...
import {actionCreators as userActions} from "../redux/modules/user";
import { useDispatch } from "react-redux";

const Login = (props) => {
		const dispatch = useDispatch();
    const [id, setId] = React.useState('');
    const [pwd, setPwd] = React.useState('');

    const changeId = (e) => {
        setId(e.target.value);
    }

    const changePwd = (e) => {
        setPwd(e.target.value);
    }

    const login = () => {
				dispatch(userActions.login({user_name: "perl"}));
    }

    return (
        <React.Fragment>
            <Grid padding={16}>
                <Text type="heading">로그인 페이지</Text>
            </Grid>
            <Grid padding={16}>
                <Input value={id} onChange={changeId} placeholder="아이디를 입력하세요."/>
                <Input value={pwd} onChange={changePwd} type="password" placeholder="비밀번호를 입력하세요."/>
            </Grid>

            <Button __click={() => {login();}}>로그인</Button>
        </React.Fragment>
    )
}

export default Login;

'프론트엔드 > React' 카테고리의 다른 글

네트워크 요청 1 - XMLHTTPRequest  (0) 2022.06.06
Mock API  (0) 2022.06.05
ContextAPI()  (0) 2022.06.04
상태관리  (0) 2022.06.04
async, await  (0) 2022.06.04
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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 31
글 보관함