【问题标题】:How to use map function for hooks useState properties dynamically如何动态使用 map 函数来挂钩 useState 属性
【发布时间】:2020-06-27 20:17:39
【问题描述】:

我的问题和this one差不多。

在这种情况下,这个人有一张以硬编码方式创建的状态地图:

const App = props => {
  const [state, changeState] = useState({
    name: "",
    eventTitle: "",
    details: "",
    list: "",
    toggleIndex: "",
    editName: "",
    editEventTitle: "",
    editDetails: "",
  });

不同之处在于我想动态创建这些状态,从另一个组件接收它们。我试过这样的东西,但显然没有用:

const App = props => {
  const [state, changeState] = useState({
    props.inputs.map((input, i) =>
      input = ""
    )
  });

你知道有什么解决办法吗?

【问题讨论】:

  • props.inputs 长什么样子?
  • @NicholasTower 它有一个输入名称列表,我希望它们附加一个状态
  • { "tag": "1231", "description": "Lorem Ipsum", "inputs": [ "Field1", "Field2", "Field3", "Field4", ] };
  • 你可能需要将reduce props.inputs 放入一个新对象中。
  • Christos' 答案,这正是我的意思。

标签: reactjs react-hooks setstate


【解决方案1】:

假设props.input 只是您想要的键的数组,您可以通过遍历数组并使用[] 动态分配状态对象键来填充状态对象

const [state, changeState] = useState({});

useEffect(() => {
    props.input.forEach(item => changeState(prevState => ({...prevState, [item]: "" })));
}, [props.input])

【讨论】:

  • 这对我不起作用,{...prevState 给我declaration or statement expected, [item]: "" }); 给我',' expected。这段代码是如何工作的?
  • 对不起,我错过了内部()(现在添加到编辑中)。因为您可以通过使用[](即obj[variable])通过变量访问对象键,所以您可以利用它在遍历数组时动态分配它们。回调只允许您使用 ... 扩展语法来包含 changeState 中已经存在但在每次修改它以添加下一个元素时未明确定义的其余键:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 我在({...prevState, [item]: "" })); 的末尾还有')' expected,在分号中。我理解 forEach 部分,但这部分是做什么的, [props.input])
  • 糟糕,我忘了关闭 forEach(已修复)。在这种情况下,我会在组件通过 useEffect (reactjs.org/docs/hooks-effect.html) 安装时触发此操作,然后将 [props.input] 指定为其第二个参数,以表示它也会在父组件更新 props.input 时发生。我只是假设这是一种预期的行为,但您可以选择将其修改为您喜欢的任何方式(即仅在安装上一次,仅此而已)。
【解决方案2】:

您可以通过将props.inputs 直接与状态结合使用reduce 来从inputs 数组创建一个新对象:

const App = props => {
  const [state, changeState] = useState(
    props.inputs.reduce((acc, cur, arr) => ({
      [cur]: "",
      ...acc
    }), {})
  );

  return (
    <ul>
      {Object.entries(state).map(([name, value], index) => (
        <li key={`li-${index}`}><strong>{name}</strong>: {`"${value}"`}</li>
      ))}
    </ul>
  );
}

如果我们这样使用:

<App inputs={['name', 'details', 'list', 'editName']}/>

我们会得到这样的结果:

editName: ""
list: ""
details: ""
name: ""

您可以查看 Stackblitz here 的工作情况。

【讨论】:

  • 希望看到关于为什么这被否决的论点。 useState 在初始化时可以访问组件道具,因此这将适用于创建组件时传递的动态道具。如果我们有更多需要在渲染时更改的动态道具,我们当然可以使用useEffect 钩子。
  • 我没有对此投反对票,因为我感谢任何帮助。尽管如此,我还是尝试了这个建议,它只是创建了一个包含输入名称列表的状态,而不是一个类似地图的结构,它将保存输入字段的名称和值
  • props.inputs 是一个数组。
  • @EmileBergeron 我误解了这个问题,没有意识到props.inputs 是我们需要使用元素作为键的数组。
  • @PedroVieira 你可以使用reduce 做你想做的事。请检查我的更新答案。
【解决方案3】:

在我的情况下,我试图在单击映射项目时获取项目唯一 ID,并打开一个对话框以确认要删除的选定项目,如下所示

export const StatsTable = (props) => {
  const [itemUid, setItemUid] = useState('')
  const [open, setOpen] = useState(false)

  const handleClickOpen = () => {
    setOpen(true)
  }

  console.log('====================================')
  console.log(itemUid)
  console.log('====================================')
...
 return (
...
  {items.map((item) => {
...
    <Button
      type="submit"
      onClick={() =>
        handleClickOpen(setItemUid(item.uid))
      }
     >
       Delete
     </Button>
   }
}

...

Image Example

【讨论】:

    猜你喜欢
    • 2020-05-31
    • 2022-01-03
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2022-01-23
    • 2021-01-27
    相关资源
    最近更新 更多