在 React js 中使用选中的处理程序实现动态复选框

Implement dynamic checkbox with checked handler in React js

我在为数组的动态复选框设置状态时遇到问题,使用选中的处理程序将对象从 false 更改为 true。

下面是我的代码:

const [form, setForm] = useState({
    tags:[
     { name: "Athletic/Higher caloric", isChecked: false },
     { name: "Aggressive Weight Loss", isChecked: false },
     { name: "Quick and Easy", isChecked: false } ]})

const onCheckedHandler = (index) => {
      const updatedTags = 
        form.tags.map((tag, i) => {
           if (index === i) {
             form.tags[i].isChecked = !form.tags[i].isChecked;
             } 
           return { tag }; 
        }); 

    setForm(updatedTags);


return (
   {form.tags.map((tag, i) => (
        <div>
        <label>{tag.name}</label> 
        <input 
           type="checkbox"
           checked={tag.isChecked}
           onChange={(event) => onCheckedHandler(i)}
           key={i} /> 
        </div>
       ))})

我收到此错误:“未捕获类型错误:无法在创建时读取未定义(读取 'map')的属性(第 107 行)”

但是第 107 行只是另一个有效且完全不相关的地图函数的开始。我究竟做错了什么?我尝试避免使用 if 语句直接在对象中改变 isChecked 值。也许这就是我设置状态的方式?

问题可能出自这里:

return (
   {form.tags.map((tag, i) => (
        <div>
        <label>{tag.name}</label> 
        <input 
           type="checkbox"
           checked={tag.isChecked}
           onChange={(event) => onCheckedHandler(i)}
           key={i} /> 
        </div>))}
)

问题是您正在尝试使用 form 状态进行渲染,该状态在(组件的)安装时可能是 undefined。正如你的错误所说 cannot read property of undefined, reading map 它可能指的是 form.tags 未定义并且无法读取它的地图。

一个好主意是在渲染之前检查您尝试渲染的内容是否已定义。例如:

return (
   {form.tags ? form.tags.map((tag, i) => (
        <div>
        <label>{tag.name}</label> 
        <input 
           type="checkbox"
           checked={tag.isChecked}
           onChange={(event) => onCheckedHandler(i)}
           key={i} /> 
        </div>)) : <div>Loading</div>}
)

据我了解:

  • 初始状态是一个对象const [form, setForm] = useState({...});
  • 这有一个名为 tags 的道具。
  • 但是,变量updatedTags(在handler-method中)是一个数组。这不是一个对象。
  • 因此,setForm(updatedTags) 会将 form 设置为一个数组,其中不会有任何名为 tags
  • 的属性

因此,请尝试像这样更改处理程序:

const onCheckedHandler = (index) => {
  setForm(prev => ({
    ...prev,
    tags: [
      ...prev?.tags?.map(
        ({isChecked, ...rest}, idx) => (
          idx === index
          ? {...rest, isChecked: !isChecked}
          : {...rest, isChecked}
        )
      )
    ]
  }));
};

此外,请在 return 上尝试映射之前使用检查。可能会尝试这样的事情:

form?.tags?.map(...)

form && form.tags && Array.isArray(form.tags) && form.tags.map(...)