I have two user settings options. One is "enable cascading panels", and the other is "include attachments".
I have set up state variables and toggle functions to pass down to the child components so that when I click on either, the parent is able to toggle between the values. The issue is that when I click on either, the other one executes as well. Did I miss a step in setting these up?
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>
Could someone clarify what I am doing wrong here?
You should change your toggle functions in such way:
this.setState((prevState) => (
{
userToggleSettings:
{
...prevState.userToggleSettings, // ---> added
cascadingPanels: !prevState.userToggleSettings.cascadingPanels
}
}
));
React doesn't perform a "deep merge", i.e. the nested objects are not merged. Only top level properties are merged.
So the way you had it you were losing whatever was there inside the userToggleSettings
object, after doing setState
.