使用 React 钩子,我如何更新通过 props 传递给 child 的 object?

Using React hooks, how can I update an object that is being passed to a child via props?

parent 组件包含一个 object 数组。 它在数组和 returns 上映射每个 object 的 child 组件,并用 object 的信息填充它。 在每个 child 组件中都有一个输入字段,我希望它允许用户更新 object,但我不知道如何去做。 在钩子、道具和 object 不变性之间,我在概念上迷失了。 这是 parent 组件的简化版本:

const Parent = () => {
  const [categories, setCategories] = useState([]);

  useEffect(()=>{
    // makes an axios call and triggers setCategories() with the response
  }

  return(
    categories.map((element, index) => {
      return(
        <Child
          key = {index}
          id = {element.id}
          firstName = {element.firstName}
          lastName = {element.lastName}
          setCategories = {setCategories}
    })
  )
}

这里是 child 组件的简化版本:

const Child = (props) => {
  return(
    <h1>{props.firstName}</h1>
    <input
      defaultValue = {props.lastName}
      onChange={()=>{
        // This is what I need help with.
        // I'm a new developer and I don't even know where to start.
        // I need this to update the object's lastName property in the parent's array.
      }}
  )
}

也许在不知情的情况下,您已经 提升了状态 :基本上,您将状态保留在 Parent 组件中,而不是在 Child 组件中=].
这是一个用过的模式,没有错:你只是错过了一个允许 children 更新 Parent 状态的句柄函数:为了做到这一点,你需要实现一个 handleChangeParent 组件上,然后将它作为 props 传递给每个 Child.

看看这个代码示例:

const Parent = () => {
    const [categories, setCategories] = useState([]);

    useEffect(() => {
        // Making your AXIOS request.
    }, []);

    const handleChange = (index, property, value) => {
        const newCategories = [...categories];
        newCategories[index][property] = value;

        setCategories(newCategories);
    }

    return categories.map((c, i) => {
        return (
            <Child
                key={i}
                categoryIndex={i}
                firstName={c.firstName}
                lastName={c.lastName}
                handleChange={handleChange} />
        );
    });
}

const Child = (props) => {
    ...

    const onInputChange = (e) => {
        props.handleChange(props.categoryIndex, e.target.name, e.target.value);
    }

    return (
        ...
        <input name={'firstName'} value={props.firstName} onChange={onInputChange} />
        <input name={'lastName'} value={props.lastName} onChange={onInputChange} />
    );
}

一些你可能不知道的事情:

  • 通过为 input 使用属性 name,您可以只对所有 input 元素使用一个处理函数。在函数内部,在本例中为 onInputChange,您可以使用 e.target.name;
  • 检索该信息
  • 请注意,我在您的 useEffect 中添加了一个空数组依赖项:如果没有它,useEffect 将在每次渲染时都有 运行。我不认为那是你想要的。
    相反,我想你只想在挂载组件时执行请求,这可以通过 n 个空数组依赖项来实现;