Состояние компонента React-Redux - PullRequest
0 голосов
/ 11 июня 2018

tl; dr Я пытаюсь сохранить начальное состояние внутри компонента субконтейнера, но он обновляется до новых значений каждый раз, когда обновляется хранилище Redux.Я, вероятно, что-то упустил в конфигурации, и мне нужна помощь, чтобы разобраться.

index.tsx

const store = createStore(reducers, loadedState, enhancer);
ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    document.getElementById(containerId)
)

AppProps.ts

function mapStateToProps(state: StoreState){
  return{
    ... // app props
    userDetails: state.userDetails // array of objects fetched by id
  }
}

function mapDispatchToProps(dispatch: ReactRedux.Dispatch<actions.AppActions>){
  return{
    ... // app methods
    detailsUpdate: (props: UpdateProps) => (dispatch(actions.detailsUpdate(props: UpdateProps)))
  }
}
ReactRedux.connect(mapStateToProps, mapDispatchToProps)(App)

Actions.ts

function detailsUpdate(props: UpdateProps): UpdateUserDetails {
    return {
        type: UPDATE_USER_DETAILS,
        props: { ... }
    }
}

Reducers.ts

export function reducers(state: StoreState, action: actions.AppActions): StoreState {    
    let newState: StoreState =  {...state};
    switch (action.type) {
        case actions.UPDATE_USER_DETAILS:
        ... // reducer code
        break;
        case actions.UPDATE_PRODUCTS:
        ... // reducer code
        break;
    return newState;
}

App.tsx

const App = (allProps: IAppProps, state: StoreState) => {
  <UserDetailsContainer
    id="generalDetails"
    userDetails={allProps.userDetails.byId}
    detailsUpdate={allProps.detailsUpdate}
  />
}

UserDetailsContainer.tsx 1

class UserDetailsContainer extends
React.Component<UserDetailsContainerProps, UserDetailsState> {    
    constructor(props: UserDetailsContainerProps) {
        super(props);      
        this.state = {
            userData: props.userDetails[props.id]
        }
    }

    render(){
       <input type="text"
        value={this.props.userDetails[this.props.id].address}
      />
    }
}

detailsUpdate запускает действие UPDATE_USER_DETAILS и редуктор обновляет состояние магазина с новым значением.Теперь UserDetailsContainer получает обновленную версию userDetails из хранилища, что хорошо для отображения нового значения в элементе <input type="text">.

Однако this.state обновляется новым значением, которое, как я ожидаю, не должно происходить, так как конструктор должен вызываться только один раз (и есть).Это не позволяет мне ссылаться на начальное значение в случае, если оно мне нужно для сброса или другого.

Пожалуйста, запрашивайте недостающую информацию и / или разъяснения и игнорируйте любые опечатки, так как приложение работает без ошибок.

1 Компонент обычно отображает другой презентационный компонент для <input type="text">, который я здесь опущен для краткости.

Спасибо!

1 Ответ

0 голосов
/ 11 июня 2018

Следующее делает только поверхностную копию объекта состояния.

let newState: StoreState =  {...state};

Поэтому, если вы назначите

this.state = {
   userData: props.userDetails[props.id]
}

, а затем измените массив внутри вашего редуктора, вы также изменитесостояние компонента, так как он ссылается на один и тот же объект.Это также идет вразрез с концепцией избыточности - редуктор не должен изменять свои аргументы.

Обратите внимание, что эта точная ошибка выделена в документах по избыточности: https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns#common-mistake-2-only-making-a-shallow-copy-of-one-level

...