title: Next.js (REACT) Not firing "onChange" event on first "uncheck" on checkboxes
body: <p>I have made a grid of &quot;checkboxes&quot; for permissions within the component. For some reason, it doesn't trigger the first &quot;onChange&quot; event if the action is unchecking a checkbox, which loads its state by default from the server. Guidance on what I am doing wrong will be highly appreciated, thank you so much!</p>
  <p><strong>UPDATE</strong>: Using checked instead of &quot;defaultChecked&quot; seems to fix the issue, however, then I come up with this error:</p>
  <blockquote>
  <p>&quot;Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: ....&quot;</p>
  </blockquote>
  <p>Here's the Component:</p>
  <pre><code>import { useState } from &quot;react&quot;;
  import { Form } from &quot;react-bootstrap&quot;;
  import api from &quot;../../lib/api&quot;;
  import useForm from &quot;../../lib/useForm&quot;;
  
  export default function PermissionSelector({ user, permissions }) {
      let initialState = permissions;
  
      const [loaded, setLoaded] = useState(false);
      const [loading, setLoading] = useState(false);
      const [error, setError] = useState(null);
      const [success, setSuccess] = useState(null);
  
      let { inputs, handleChange, resetForm, setForm } = useForm(initialState);
  
      if (!loaded) {
          setForm(permissions);
          setLoaded(true);
      }
  
      const handleSubmit = async (e) =&gt; {
          e.preventDefault();
          setLoading(true);
          setError(false);
          setSuccess(false);
  
          console.log(inputs);
  
          await api()
              .put(`/user-permissions/${user.id}`, inputs)
              .then((res) =&gt; setSuccess(&quot;Permissions have been updated!&quot;))
              .catch((err) =&gt; {
                  if (err.status === 422) {
                      setError(err.data.message);
                  }
              });
  
          setLoading(false);
      };
  
      return (
          &lt;&gt;
              &lt;style global jsx&gt;
                  {`
                      .permissions {
                          overflow: hidden;
                      }
                      .permissions li {
                          list-style: none;
                          display: block;
                          float: left;
                          width: 50%;
                      }
  
                      @media only screen and (min-width: 768px) {
                          .permissions li {
                              width: 25%;
                          }
                      }
                  `}
              &lt;/style&gt;
              {success &amp;&amp; &lt;div className=&quot;alert alert-success&quot;&gt;{success}&lt;/div&gt;}
              {error &amp;&amp; &lt;div className=&quot;alert alert-danger&quot;&gt;{error}&lt;/div&gt;}
              &lt;Form className=&quot;form-primary&quot; onSubmit={handleSubmit}&gt;
                  &lt;ul className=&quot;permissions&quot;&gt;
                      {loaded &amp;&amp;
                          Object.keys(permissions).map((permission) =&gt; (
                              &lt;li key={permission}&gt;
                                  &lt;Form.Check
                                      type=&quot;checkbox&quot;
                                      id={permission}
                                      label={permission.split(&quot;permissions.&quot;)[1]}
                                      name={permission}
                                      defaultChecked={inputs[permission]}
                                      onChange={handleChange}
                                      custom
                                  /&gt;
                              &lt;/li&gt;
                          ))}
                  &lt;/ul&gt;
  
                  &lt;div className=&quot;btn-container&quot;&gt;
                      &lt;button
                          type=&quot;submit&quot;
                          className=&quot;btn-submit&quot;
                          disabled={loading}
                      &gt;
                          {loading &amp;&amp; &quot;Updating...&quot;}
                          {!loading &amp;&amp; &quot;Update&quot;}
                      &lt;/button&gt;
                  &lt;/div&gt;
              &lt;/Form&gt;
          &lt;/&gt;
      );
  }
  </code></pre>
  <p>Here's the useForm:</p>
  <pre><code>import { useEffect, useState } from &quot;react&quot;;
  
  export default function useForm(initial = {}) {
      const [inputs, setInputs] = useState(initial);
  
      const initialValues = Object.values(initial).join(&quot;&quot;);
  
      useEffect(() =&gt; {
          setInputs(initial);
      }, [initialValues]);
  
      function handleChange(e) {
          let { value, name, type } = e.target;
  
          console.log(type, name, value);
  
          if (type === &quot;checkbox&quot;) {
              console.log(e.target.checked);
              value = e.target.checked;
          }
  
          if (type === &quot;number&quot;) {
              value = parseInt(value);
          }
  
          if (type === &quot;file&quot;) {
              [value] = e.target.files;
          }
  
          setInputs({
              ...inputs,
              [name]: value,
          });
      }
  
      function resetForm() {
          setInputs(initial);
      }
  
      function setForm(inputs) {
          setInputs(inputs);
      }
  
      function clearForm() {
          const blankState = Object.fromEntries(
              Object.entries(inputs).map(([key, value]) =&gt; [key, &quot;&quot;])
          );
          setInputs(blankState);
      }
  
      return {
          inputs,
          handleChange,
          resetForm,
          clearForm,
          setForm,
      };
  }
  </code></pre>