React

#16 Redux part2

Sila 2022. 5. 7. 22:41

지난번에 배운 redux의 기능을 약간 더 응용해 사용해보자.

 

우리가 SPA를 만들 때, 다양한 변수들이 다양한 형태로 state에 저장되어 관리를 받을 것이고,

 

페이지의 기능이 늘어날수록 그 상태의 형태 또한 굉장히 복잡해질 것이다.

 

예를 들어 간단한 게시판을 만드는데도 다음과 같이 복잡한 initialState가 필요하다.

 

/*  app.js  */

const redux = require('redux')
const { createStore } = redux

const initialState = {
    user:{
        userid:'web7722',
        username:'ingoo'
    },
    comment:{
        list:[{ idx:0, content:'asdf', date:'2022-05-03' }]
    },
    category:{
        mainCd:[ 
            {  
                idx:0,
                name:'board',
                subCate:[{idx:0, name:'notice'}, {idx:1,name:'freeboard'}]
            }
        ]
    },
}

 

단순히 회원 정보와 댓글, 게시판 카테고리만을 가진 최소한의 어플리케이션도 이 정도로 복잡해진다.

 

이 경우 가령 1번째 subcategory를 바꾸려면 state.category.mainCd... 순으로 하나하나 경로를 찾아가야 한다.

 

이런 경우 코드의 관리가 힘들기 때문에 각각의 state를 이루는 요소들을 나누어 따로 관리하고,

 

이 나누어진 코드들을 마지막에 하나로 합쳐주는 기능이 redux에 존재한다.

 

저번 글에서 redux를 console.log로 불러왔을 때 있던 함수 중 하나인 combineReducer 함수이다. 

 

이름대로 reducer를 combine 해준다고 생각을 하면 된다.

 

reducer 뿐만 아니라 각각의 reducer가 관리하는 state 요소들도 분리해 관리하는 것이 가능하다.

 

우선 initialState들을 다음과 같이 분리한다.

 

/*  app.js  */

const initialState_user = {
    userid: 'qwerty',
    userpw : 1111 
}

const initialState_comment = {
    list:[{ idx:0, content:'asdf', date:'2022-05-03' }]
}

const initialState_category = {
    mainCd:[ 
        {  
            idx:0,
            name:'board',
            subCate:[{idx:0, name:'notice'}, {idx:1,name:'freeboard'}]
        }
    ]
}

 

각 변수들을 잘보면 아까 전처럼 요소들을 중간에서 하나로 묶어주던 user, comment, category가 사라지고,

 

그 내용들이 바로 초기 state값에 대입되는 것을 알 수 있다.

 

사라진 객체의 변수명 user, category, comment들은 각 리듀서의 이름으로 대체될 것이다.

 

각각의 리듀서와 action도 작성해준다.

 

/*  app.js  */

(...중략)

// user
const ADD = 'USER/ADD'
const CHANGE_ID = (payload) => ({type:ADD, payload})

const user = (state = initialState_user, action) => {
    switch (action.type) {
        case ADD :
            return {
                ...state,
                userid: action.payload.userid,
                userpw: action.payload.userpw
            }
        default:
            return state
    }
}

// comment
const CADD = 'COMMENT_ADD'
const COMMENT_ADD = (payload) => ({type:CADD, payload})

const comment = (state = initialState_comment, action) => {
    switch (action.type) {
        case CADD :
            return {
                ...state,
                list: [...state.list, {idx:1, content:action.payload.content,  date: '2022-05-03'}]
            }
        default :
            return state
    }
}

// category
const TADD = 'CATEGORY/ADD'
const CATE_ADD = (payload) => ({type:TADD, payload})

const category = (state = initialState_category, action) => {
    switch (action.type) {
        case TADD :
            return {
                ...state,
                mainCd:[...state.mainCd, { idx:1, name: action.payload.cate, subCate:[]}]
            }
            default :
                return state
    }
}

 

이제 이렇게 쪼개서 만든 리듀서와 함수들, state들을 하나로 합친다.

 

/*  app.js  */

const redux = require('redux')
const { createStore, combineReducers } = redux
// combineReducer 함수를 redux로부터 추가로 가져온다.

(...중략)

const rootReducer = combineReducers({
    user,
    comment,
    category
})
// 각 리듀서들을 combineReducers 함수로 합쳐 rootReducer 변수에 넣는다.

const store = createStore(rootReducer)
// store에 rootReducer 변수를 대입한다.

 

여기까지 하고 state를 console.log로 불러오면 다음과 같다.

 

/*  app.js  */

console.log(store.getState())

/*
{
  user: { userid: 'qwerty', userpw: 1111 },
  comment: { list: [ [Object] ] },
  category: { mainCd: [ [Object] ] }
}
*/

 

우리가 초기 상태를 설정할 때 따로 변수를 서언해 대입하지 않았음에도 각 객체들이 알아서

 

각 리듀서의 이름을 key값으로 가지는 것을 알 수 있다.

 

각각의 state들을 변경해보자.

 

/*  app.js  */

(...중략)

store.dispatch(CHANGE_ID({userid: 'sila', userpw: 1357 }))
console.log(store.getState().user)

store.dispatch(CATE_ADD({cate: 'cate2'}))
console.log(store.getState().category)

store.dispatch(COMMENT_ADD({content: 'this is content of new comment'}))
console.log(store.getState().comment)

 

각 state들이 잘 변경되었다면 이제 이 각각의 코드들을 다른 파일들로 분리해보자.

 

reducers 폴더를 만들고 그 안에 category.js, comment.js, user.js 파일을 만든 후,

 

리듀서와 초기 상태, action 생성 함수를 넣고 export 해주면 된다.

 

/*  reducers/user.js  */

const initialState = {
    userid: 'qwerty',
    userpw : 1234
}

const ADD = 'USER/ADD'
const CHANGE_ID = (payload) => ({type:ADD, payload})

const user = (state = initialState, action) => {
    switch (action.type) {
        case ADD :
            return {
                ...state,
                userid: action.payload.userid,
                userpw : action.payload.userpw
            }
        default:
            return state
    }
}

module.exports = {
    user,
    CHANGE_ID
}

 

/*  reducers/comment.js  */

const initialState = {
    list:[{ idx:0, content:'asdf', date:'2022-05-03' }]
}

const CADD = 'COMMENT_ADD'
const COMMENT_ADD = (payload) => ({type:CADD, payload})

const comment = (state = initialState, action) => {
    switch (action.type) {
        case CADD :
            return {
                ...state,
                list: [...state.list, {idx:1, content:action.payload.content,  date: '2022-05-03'}]
            }
        default :
            return state
    }
}

module.exports = {
    comment,
    COMMENT_ADD
}
/*  reducers/category.js  */

const initialState = {
    mainCd:[{
        idx:0,
        name: 'board',
        subCate: [{idx:0, name:'notice'}, {idx:1, name:'freeboard'}]
    }]
}

const TADD = 'CATEGORY/ADD'
const CATE_ADD = (payload) => ({type:TADD, payload})

const category = (state = initialState, action) => {
    switch (action.type) {
        case TADD :
            return {
                ...state,
                mainCd:[...state.mainCd, { idx:1, name: 'qwert', subCate:[]}]
            }
            default :
                return state
    }
}

module.exports = {
    category,
    CATE_ADD
}

 

이제 app.js로 돌아와 다음과 같이 코드를 정리할 수 있다.

 

/*  app.js  */

const redux = require('redux')
const { createStore, combineReducers } = redux

const { user, USER_ADD } = require('./reducers/user.js')
const { comment, COMMENT_ADD } = require('./reducers/comment.js')
const { category, CATE_ADD } = require('./reducers/category.js')

const rootReducer = combineReducers({
    user,
    comment,
    category
})

const store = createStore(rootReducer)

console.log(store.getState())

store.dispatch(CHANGE_ID({userid: 'sila', userpw: 1357 }))
console.log(store.getState().user)

store.dispatch(CATE_ADD({cate: 'cate2'}))
console.log(store.getState().category)

store.dispatch(COMMENT_ADD({content: 'qwewgfdhzxcv'}))
console.log(store.getState().comment)

 

'React' 카테고리의 다른 글

error record : styled-compoenents  (0) 2023.03.19
#17 Router  (0) 2022.05.08
#15 Redux part1  (0) 2022.05.07
#14 useMemo, useCallback  (0) 2022.05.02
#13 useReducer  (0) 2022.05.01