I'm trying to make a switch become enabled/disabled whenever the user interacts with it. This is done by using a onChange
event, which then changes a context stats key, value
However, when console logging the output. The state does not seem to be changing.
Context is an object of the values below, by default all values are null. context after update:
newSettings:
anti_scam:
enabled: null
log_channel: null
punishment_type: null
tmpSettings obj
newSettings:
anti_scam:
enabled: true
log_channel: null
punishment_type: null
As you can see, the value of enabled
is changed. But the react context state is not. This means the switch is always either disabled, or enabled depending on the users settings, and they cannot change it.
What I have tried Originally I was using a mutable obj. But then I found out that sometimes this does not cause react to re-render the page. So, I switched to making an immutable copy, and modifying the values I wish to change from that. But this still has not fixed the problems.
Any help would be very much appreciated.
const EnableSwitch = () => {
const { context, setSaveEnabled } = useContext(SaveContext);
const handleChange = (event) => {
const tmpSettings = JSON.parse(JSON.stringify(context));
tmpSettings.newSettings.anti_scam.enabled = event.target.checked;
setSaveEnabled(tmpSettings);
};
return (
<Fade bottom>
<div>
<Switch
checked={context.newSettings.anti_scam.enabled}
onChange={handleChange}
inputProps={{ "aria-label": "controlled" }}
/>
</div>
</Fade>
);
};
<SaveContext.Provider value={{ context, setSaveEnabled }}>
import { createContext } from "react";
const SaveContext = createContext({
context: {
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
}
},
setSaveEnabled: () => { }
});
export const SaveProvider = SaveContext.Provider;
export default SaveContext;
CodePudding user response:
Context is a way to get values from component A to component B, but it will not implement anything else for you. If you want to pass state from component A to component B, then component A will need to implement that state, using useState
and other such code. Since you're just using the default value, none of that is happening.
So you will need to make a component near the top of the tree that is something like this:
const Example = ({ children }) => {
const [state, setState] = useState({
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
});
const contextValue = useMemo(() => {
return {
context: state,
setSaveEnabled: /* some function which updates the state */,
}
}, [state]);
return (
<SaveContext.Provider value={contextValue}>
{children}
</SaveContext.Provider>
)
};