#javascript #reactjs #state #jsx #react-props
Вопрос:
У меня есть два варианта пользовательских настроек. Один из них — «включить каскадные панели», а другой — «включить вложения».
Я настроил переменные состояния и функции переключения для передачи дочерним компонентам, чтобы, когда я нажимаю на любой из них, родитель мог переключаться между значениями. Проблема в том, что когда я нажимаю на один из них, другой также выполняется. Неужели я пропустил какой-то шаг в их настройке?
Данные родительского компонента:
Государство:
constructor(props){
const userToggleSettings = {
cascadingPanels: true,
includeAttachments: true,
analyticsOptIn: false
};
this.state = {
userToggleSettings
};
}
Переключение функций:
toggleIncludeAttachments = () => {
this.setState((prevState) => (
{
userToggleSettings:
{
includeAttachments: !prevState.userToggleSettings.includeAttachments
}
}
));
};
toggleCascadingPanels = () => {
this.setState((prevState) => (
{
userToggleSettings:
{
cascadingPanels: !prevState.userToggleSettings.cascadingPanels
}
}
));
};
includeAttachmentsClickHandler = () => {
this.toggleIncludeAttachments();
}
cascadingPanelsClickHandler = () => {
this.toggleCascadingPanels();
}
Передача значений и функций в качестве реквизитов:
<ChildComponent
attachmentsSwitchHandler={this.toggleIncludeAttachments}
attachmentsSwitchValue={this.state.userToggleSettings.includeAttachments}
cascadingPanelsSwitchHandler={this.toggleCascadingPanels}
cascadingPanelsSwitchValue={this.state.userToggleSettings.cascadingPanels}
/>
Данные дочерних компонентов
Настройка событий и значений щелчков в дочернем компоненте:
<div className='child-component-container'>
<div className={'user-settings-toggle'}
onClick={props.cascadingPanelsSwitchHandler}
>
<div className={'user-settings-label'}>
{props.translations.CASCADING_PANELS}
</div>
<Switch
checked={props.cascadingPanelsSwitchValue}
translations={{
off: props.translations.off,
on: props.translations.ON
}}
/>
</div>
<div className={'user-settings-toggle'}
onClick={props.attachmentsSwitchHandler}
>
<Switch
checked={props.attachmentsSwitchValue}
translations={{
off: props.translations.off,
on: props.translations.ON
}}
/>
<div className={'user-settings-label'}>
{props.translations.ALWAYS_INCLUDE_ATTACHMENTS}
</div>
</div>
ДЕМОНСТРАЦИЯ:
Может кто-нибудь прояснить, что я здесь делаю не так?
Ответ №1:
Вы должны изменить свои функции переключения таким образом:
this.setState((prevState) => (
{
userToggleSettings:
{
...prevState.userToggleSettings, // ---> added
cascadingPanels: !prevState.userToggleSettings.cascadingPanels
}
}
));
React не выполняет «глубокое слияние», т. е. вложенные объекты не объединяются. Объединяются только свойства верхнего уровня.
Таким образом, так, как у вас это было, вы теряли все, что было внутри userToggleSettings
объекта, после того, как сделали setState
.