programing

개체 내에서 배열을 푸시하는 동안 돌연변이를 방지하는 방법

prostudy 2022. 3. 15. 20:53
반응형

개체 내에서 배열을 푸시하는 동안 돌연변이를 방지하는 방법

나는 회사를 가지고 있는 물건을 가지고 있고 회사 안에는 여러 팀이 있다.

  company: {
    teams: [
      {
        name: 'test team',
        description: 'dddd',
        team_manager: null,
        company: '592577d5b591966c8e535865',
        permalink: 'test-team',
        createdAt: '2017-05-30T07:38:58.983Z',
        updatedAt: '2017-05-30T07:38:58.983Z',
        id: '592d219277923054118e7299'
      }
    ],
    name: 'test company2',
    createdAt: '2017-05-24T12:08:53.418Z',
    updatedAt: '2017-05-24T12:08:53.419Z',
    id: '592577d5b591966c8e535865'
  }
}

한 팀이 추가되면, 나는 팀을 배열로 밀어넣기 위해 이 환원기를 사용하고 있다.

case types.ADD_TEAM_SUCCESS :
  return Object.assign({}, state, state.teams.push(action.newTeam));

그러나 콘솔에서 다음과 같은 경고를 받고 있다.

'오류: 다음 경로에서 디스패치 내부에서 상태 돌연변이가 감지됨:company.teams.0'

객체를 닫고 새로운 팀을 어레이에 밀어넣기 위한 올바른 방법은 무엇인가?

이 링크 참조

es2015를 사용하고 있다면 다음과 같은 것을 할 수 있다.

return Object.assign({}, state, { teams: [...state.teams, action.newTeam] });

개체를 다음으로 직접 푸시하는 경우state.teams먼저 복사하고 대신 그것을 사용해야 한다.스프레드 연산자를 사용할 수 없는 경우 상태를 슬라이스할 수 있다.팀을 새로운 변수로 만들고 대신 그 쪽으로 밀어붙인다.

Object.assign() 앞에 설명된 것처럼 개체의 복제 작업이 깊지 않음.

내 제안은 당신의 상점을 정상화하고 회사와 팀 두 개의 상점으로 나누는 것이다.

combinateReducer를 사용하여 이것을 하나의 저장소에 연결하는 것보다 당신은 환원기를 단순화하고 코드를 더 읽기 쉽게 만들 것이다.또한 당신은 공연으로 노는 것 이상을 할 수 있다.

내 말은...만약 당신이 단지 회사와 함께 일하는 컴포넌트를 가지게 될 것이고 당신은 팀내 변화를 가지게 될 것이고 당신은 쉽게 재입사를 피할 것이다.

Dan Abramov grate 비디오 튜토리얼 확인 Redx: 상태 셰이프 표준화

어떻게든 그렇게 하겠다(타입체 코드는 미안하다)

export interface ICompanyItem {    
    name: string;    
    id: string;
    createdAt: Date;
    updatedAt: Date;    
}

export interface ITeamItem {
    id: string;
    companyId: string
    name: string;
    description: string;
    team_manager: string;
    createdAt: Date;
    updatedAt: Date;
}

export interface ICompaniesState {
    items: { [id: string]: ICompanyItem };
}

export interface ITeamsState {
    items: { [id: string]: ITeamItem };
}


export const teamsReducer: Reducer<ITeamsState> = (state: ITeamsState, action: Action) => {

    if (isActionType(action, AddNewTeamItem)) {
        let itemsClone: { [id: string]: ITeamItem } = { ...state.items, [action.id]: action.team };

        return {
            ...state,
            items: itemsClone
        };
    }

    return state || unloadedState;
};

문제는 이다Object.assign()개체 [1]의 깊은 클론을 수행하지 마십시오("딥 클론에 대한 경고" 참조).

스택에 lodash와 같은 유틸리티 라이브러리가 없는 경우 JSON 인코딩 및 디코딩을 사용하여 작업을 완료할 수 있다.

case types.ADD_TEAM_SUCCESS:
    let stateCopy = JSON.parse(JSON.stringify(state));
    state.teams.push(action.newTeam);
    return state;

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

참조URL: https://stackoverflow.com/questions/44256428/how-to-avoid-mutations-while-pushing-an-array-inside-an-object

반응형