programing

Vuex에서 상태를 정규화하는 방법

copysource 2022. 8. 28. 21:12
반응형

Vuex에서 상태를 정규화하는 방법

Vuex를 사용하여 앱을 개발 중인데, 네스트된 오브젝트에 대처하는 것이 귀찮은 상황이기 때문에 아래 예시와 같이 가능한 한 상태를 정상화(평탄화)하려고 합니다.

users: {
    1234: { ... },
    46473: { name: 'Tom', topics: [345, 3456] }
},
userList: [46473, 1234]

질문입니다.API 응답이 다음과 같을 때 의 "최적의" 방법은 무엇입니까?

data: [
    {id: 'u_0001', name: 'John', coments: [{id: 'c_001', body: 'Lorem Ipsum'}, {...}],
    {id: 'u_0002', name: 'Jane', coments: [{id: 'c_002', body: 'Lorem Ipsum'}, {...}],
    {...}
] 

예를 들어 다음과 같이 가정하면comments의 서브모듈입니다.users:

옵션 1:

// action on the user module
export const users = ({ commit, state }, users) => {
    commit(SET_USERS, users)
    commit('comments/SET_COMMENTS', users)
}


// mutation on the user module
[types.SET_USERS] (state, users) {
     state.users = users.reduce((obj, user) => {
         obj[user.id] = {
             id: user.id, 
             name: user.name,
             comments: user.comments.map(comment => comment.id)
         } 
         return obj
     }, {})
    state.userIds = users.map(user => user.id)
},


// mutation on the comments module
[types.SET_COMMENTS] (state, users) {
    let allComments = []
    users.forEach(user =>  {
        let comments = user.comments.reduce((obj, comment) => {
            obj[comment.id] = comment
            return obj
        }, {})
        allComments.push(comments)
    })

   state.comments = ...allComments
},

IMO 이 옵션은 페이지(SPA/Vue-Router)를 변경할 때마다 상태를 리셋할 필요가 없기 때문에 어떤 이유로 인해 다음과 같은 상황이 발생하지 않도록 하는 것이 좋습니다.id: u_001돌연변이가 호출될 때마다 상태가 오버라이드되기 때문에 더 이상 존재하지 않습니다만, 이 상태를 통과시키는 것은 이상하다고 느껴집니다.users array두 돌연변이에 모두 영향을 미칩니다.

옵션 2:

// action on the user module
export const users = ({ commit, state }, users) => {
    // Here you would have to reset the state first (I think)
    // commit(RESET)

    users.forEach(user => {
        commit(SET_USER, user)
        commit('comments/SET_COMMENTS', user.comments)
    })
}


// mutation on the user module
[types.SET_USER] (state, user) {
    state.users[user.id] = {
        id: user.id, 
        name: user.name,
        comments: user.comments.map(comment => comment.id)
    }  
    state.userIds.push(user.id)
},


// mutation on the comments module
[types.SET_COMMENTS] (state, comments) {
    comments.forEach(comment => {
        Vue.set(state.comments, comment.id, comment)
    })
    state.commentsIds.push(...comments.map(comment => comment.id)
},

이 경우 상태를 리셋해야 합니다.그렇지 않으면 페이지를 종료하고 다시 렌더링할 때마다 반복/이전 값이 표시됩니다.Wich는 다소 짜증나고 버그나 일관되지 않은 행동에 더 유익하다.

결론: 이러한 시나리오, 어드바이스/베스트 프랙티스는 어떻게 대처하고 있습니까?저는 이런 것들에 빠져있기 때문에 답변에 매우 감사합니다.

또한 Vue ORM, Normalizr 등의 3r 파티 라이브러리는 요구가 그다지 복잡하지 않기 때문에 피하려고 합니다.

감사합니다.

PS: 테스트 없이 작성했을 뿐이므로, 코드에 오류가 있을 수 있습니다.큰 그림에 주목해 주세요.

음, 아래 주의 우발적인 복잡성을 피하기 위해 주의 정규화를 수행할 때 주의해야 할 사항입니다.

공식 Redux 문서에서 언급한 바와 같이

  1. 각 데이터 유형은 해당 상태에서 고유한 "테이블"을 가져옵니다.
  2. 각 "데이터 테이블"은 개체의 개별 항목을 저장하고 항목의 ID를 키로 항목 자체를 값으로 해야 합니다.
  3. 개별 항목에 대한 참조는 항목 ID를 저장하여 수행해야 합니다.
  4. ID 배열은 순서를 나타내는 데 사용해야 합니다.

위의 예에서 데이터에서 용장성을 제거합니다.다음과 같은 각 정보에 대해 각 테이블을 사용할 수 있습니다.users,comments기타 등등.

{
  'users': {
    byId : {
      "user1" : {
        username : "user1",
        name : "User 1",
      },
      "user2" : {
        username : "user2",
        name : "User 2",
      },
      ...
    },
    allIds : ["user1", "user2", ..]
  },
  'comments': {
    byId : {
      "comment1" : {
        id : "comment1",
        author : "user2",
        body: 'Lorem Ipsum'
      },
      "comment2" : {
        id : "comment2",
        author : "user3",
        body: 'Lorem Ipsum'
    },
    allIds : ["comment1", "comment2"]
  }
}

이를 통해 모든 컴포넌트가 대량의 데이터 세트를 가지고 칠렌 컴포넌트에 데이터를 전달하는 대신 더 많은 컴포넌트가 접속되어 자신의 데이터 세트를 검색하고 관리하는 것을 확인할 수 있습니다.

차별 UPDATED

이후 데이터 구성 요소에 있듯이, 싱글 액션과 함께 부모 구성 요소에서 주체가 되면으로 정상화 혜택 아래 부분 달성될 수 있normalize 왔다.

  1. 보다 빠르고 데이터 접근보다 더 배열하거나 내포된 클레임들입니다.
  2. 구성 요소 사이의 느슨한 결합.
  3. 각 요소에 가게를, 따라서 진실의 단일 점은 자기 집이 있어요.

이 도움이 되면 좋겠어!

언급URL:https://stackoverflow.com/questions/55387562/how-to-achieve-state-normalization-in-vuex

반응형