Search code examples
reactjsreact-hooksantd

Switch does not change based on React.useState


In this simple "demo" in CodeSandbox: https://codesandbox.io/s/cool-fast-fi426k?file=/src/App.tsx

you can see that checked actually changes, based on an external condition (inputted text length), but this does not "physically"change the Switch

    import "./styles.css";
    import * as React from "react";
    import { Switch } from "antd";
    import { useForm } from "react-hook-form";
    
    export default function App() {
      const { register, handleSubmit } = useForm();
    
      let [checked, setChecked] = React.useState(false);
    
      const onSubmit = (data: string) => {
        console.log("data.text: ", data.text);
        let length = data.text.length;
        console.log("data.text.length: ", length);
        if (length > 5) {
          console.log("'checked' variable has to be set as TRUE");
          setChecked((checked) => true);
        } else {
          console.log("'checked' variable has to be set as FALSE");
          setChecked((checked) => false);
        }
      };
    
      const AntdOnChange = (checked) => {
        console.log(`switch to ${checked}`);
      };
    
      React.useEffect(() => {
        AntdOnChange(checked);
      }, [checked]);
    
      return (
        <div className="App">
          <form onSubmit={handleSubmit(onSubmit)}>
            <div>
              <label htmlFor="text">Text</label>
              <input id="text" placeholder="text" {...register("text")} />
            </div>
    
            <button type="submit">Submit</button>
          </form>
    
          <Switch
            checkedChildren="ON"
            unCheckedChildren="OFF"
            defaultChecked
            onChange={AntdOnChange}
          />
        </div>
      );
    }

How to pass the correctly changed value of checked variable to the Switch state ?


Solution

  • You can achieve this by doing three things

    1. Remove the useEffect that updates the checked state. If you pass the state into the switch component with that, it will cause multiple renders which will cause an error

    2. Do this in your switch component. I have added the checked prop

     <Switch
            checkedChildren="ON"
            unCheckedChildren="OFF"
            defaultChecked
            checked={checked} 
            onChange={AntdOnChange}
          />
    
    1. In your AntdOnChange function, do this. This function will work independently of whatever is added in the input
      const AntdOnChange = (checked) => {
        setChecked((checked) => !checked);
      };