Search code examples
javascriptreactjscheckboxreact-hooksuse-effect

React Jsx checked property got override


Here I'm trying to make a check box to be able to select and reset. *since it's a popup, it should be able to update by a click, not after re-rendering.

Initially, the check box was able to select normally when I put 'checked' as { checked } in UserListElement.tsx. However I need a reset function too, so I add isReset property and change 'checked' value in UserListElement.tsx to {handleOnCheck}.

Now when selected, the radio button is unselected

checked

But when I clicked 'reset', the previously selected items appears to be selected now, when everything should've been unchecked (false).

enter image description here

Appreciate all your helps.

UserList.tsx

export const UserList = (props: {
    showsUserList: boolean;handleClose: () => void;corporationId: string;currentUserId: string;samePerson: boolean;twj: string;
  }) => {
    const [isReset, setReset] = useState(false);
    .......
    const resetAll = () => {
      setReset(true);
      setCount((addedUserList.length = 0));
      setAddedUserList([]);
      setUserName('');
    };
    ......
    return ( <
      > < div > xxxxx <
      ul className = {
        `option-module-list no-list option-module-list-member ${style.personListMember}`
      } > {searchedUserList.map((user, i) => ( 
      <UserListElement user = { user }
          handleOnMemberClicked = { handleOnMemberClicked }
          isReset = { isReset }
          key = {i} />
        )) }
        </ul> 
      /div>
    <a className="is-secondary reservation-popup-filter-reset" onClick={resetAll}>
      .....
    }

UserListElement.tsx

export const UserListElement = ({
  user,
  handleOnMemberClicked,
  isReset,
}: {
  user: UserDetail;
  handleOnMemberClicked: (checked: boolean, userId: string | null) => void;
  isReset: boolean;
}) => {
  const [checked, setChecked] = useState(false);
  const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
    const checkedState = e.target.checked;
    setChecked(checkedState);
    handleOnMemberClicked(checkedState, user.userId);
  };
  const handleOnCheck = useMemo(() => {
    if (isReset) {
      setChecked(false);
    }
    return checked;
  }, [isReset]);
  return (
    <li>
      <label className={style.checkboxLabel}>
        <input type="checkbox" className={style.checkboxCircle} checked={handleOnCheck} onChange={(e) => handleOnChange(e)} />
        <span>{user.name}</span>
      </label>
    </li>
  );
};


Solution

  • Your issue here is you are returning the old value of the checked variable in useMemo (state hasn't updated checked when you return it). I would eliminate useMemo as well as the handleOnCheck variable and simply rely on updating checked via a useEffect. See below:

    useEffect(()=> {
       if(isReset) setChecked(false)
     }, [isReset])
    

    Then simply pass checked to the input:

    <input type="checkbox" className={style.checkboxCircle} checked={checked} onChange={(e) => handleOnChange(e)} />
    

    useMemo will only run once when isReset changes and since you are returning a stale value, your state doesn't update.