【问题标题】:React Jsx set checked state to false (reset button)React Jsx 将选中状态设置为 false(重置按钮)
【发布时间】:2022-01-21 19:58:28
【问题描述】:

我正在尝试重置此列表中选定的单选按钮, 但是它不起作用,因为 我之前将输入检查从{checked} 更改为{user.checked}。参考下方UserListElement.tsx

因此,我尝试了以下两种方法。

  1. 在useEffect()中,设置user.userId = false

useEffect(() => {
    user.checked = false;
  }, [isReset, user]);

→ 没有变化。

  1. setCheckedtrue 时添加的UserIds 包含 user.userId

 if (addedUserIds.includes(`${user.userId}`)) {
    setChecked(true);
  }

→ 未处理的运行时错误 错误:重新渲染过多。 React 限制渲染次数以防止无限循环。

对如何使这项工作有任何建议?

UserListElement.tsx

export const UserListElement = ({
  user,
  handleOnMemberClicked,
  isReset,
}: {
  user: UserEntity;
  handleOnMemberClicked: (checked: boolean, userId: string | null) => void;
  isReset: boolean;
}) => {
  const [checked, setChecked] = useState(user.checked);
  const addedUserIds = addedUserList.map((item) => item.userId) || [];

  const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
    const checkedState = e.target.checked;
    setChecked(checkedState); //not called
    user.checked = checkedState;
    handleOnMemberClicked(checkedState, user.userId);
  };
  useEffect(() => {
    setChecked(false);
  }, [isReset, user]);

  if (addedUserIds.includes(`${user.userId}`)) {
    user.checked = true;
    // setChecked(true) cause runtime error (infinite loop)
  }

  return (
    <li>
      <label className={style.checkboxLabel}>
        <input
          type="checkbox"
          className={style.checkboxCircle}
          checked={user.checked}
          // checked={checked}
          onChange={(e) => handleOnChange(e)}
        />
        <span>{user.name}</span>
      </label>
    </li>
  );
};

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(!isReset);
      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}>
      .....
    }

UseAddUserList.tsx

export class UserDetail {
  constructor(public userId: string | null, public name: string | null) {}
}

export let addedUserList: UserDetail[] = [];
export let setAddedUserList: Dispatch<SetStateAction<UserDetail[]>>;

export const useAddUserList = (idList: UserDetail[]) => {
  [addedUserList, setAddedUserList] = useState(idList);
};

进一步说明:

默认视图

搜索的选项(显示过滤列表)

我使用user.checked,因为仅使用选中时,选中状态不会从过滤列表视图继续到完整视图(例如,当我删除搜索词或关闭弹出窗口时)。

【问题讨论】:

    标签: javascript reactjs checkbox react-hooks use-effect


    【解决方案1】:

    这个问题的真正答案是状态应该保存在您的组件中。复选框的状态应保存在UsersList 中,并作为道具传入。

    export const UserListElement = ({
      user,
      handleOnMemberClicked,
      isChecked
    }: {
      user: UserEntity;
      handleOnMemberClicked: (checked: boolean, userId: string | null) => void;
      isChecked: boolean;
    }) => {
       // no complicated logic in here, just render the checkbox according to the `isChecked` prop, and call the handler when clicked
    }
    

    在用户列表中

    
    return searchedUserList.map(user => (
       <UserListElement 
           user={user} 
           key={user.id} 
           isChecked={addedUserIds.includes(user.id)} <-- THIS LINE
           handleOnMemberClicked={handleOnMemberClicked}
        />
    )
    

    您可以看到您几乎已经弄清楚了,因为您在孩子身上这样做了:

      if (addedUserIds.includes(`${user.userId}`)) {
        user.checked = true;
        // setChecked(true) cause runtime error (infinite loop)
      }
    

    这向您表明 checkdd 值完全取决于父级中的状态,这意味着子级中实际上没有状态。

    另外,在 React 中,永远不要改变事物(props 或 state),例如 - user.checked = true - 这是一种万无一失的方式,会给你留下一个会花费你大量时间的 bug。 p>

    希望这能有所启发

    【讨论】:

      【解决方案2】:

      在您的UserListElement.tsx 中,您在渲染中设置状态,这会触发再次渲染组件,并再次设置再次触发重新渲染的状态,并且循环继续。尝试将你的条件放在useEffect 调用中,你也会改变道具,所以不要设置user.checked = true。而是从定义它的父组件调用 setter。

      useEffect(() => {
        setChecked(false);
        if (addedUserIds.includes(user.userId)) {
          setChecked(true);
        }
      }, [user]);
      
      

      【讨论】:

      • 虽然这可能有效,但 React 中的一个常见问题是人们尝试在 props 更改时同步本地状态。在这种情况下,他们应该只是使用道具并完全摆脱本地状态。如果您正在同步本地 state 和 props 0,您的组件不拥有数据,它来自上面,因此不是 state。
      • 另外,isReset 不是这个效果的依赖。
      • @Adam 是正确的。
      猜你喜欢
      • 2022-01-05
      • 2021-10-01
      • 2021-06-16
      • 2018-07-07
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      相关资源
      最近更新 更多