Home > other >  React state not changing, when using setState
React state not changing, when using setState

Time:03-22

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>
  )
};
  • Related