开发者问题收集

使用 React Hooks,当我将 prop 从父组件传递到子组件时,子组件中的 prop 未定义

2021-08-11
3347

我想做什么?

我想设置一个对象数组,其中数组中的值取决于父组件。

当前尝试执行此操作的代码是什么?

以下是简化的不同文件:

// Parent.

export default function Parent() {
  const [filePaths, setFilePaths] = useState();

  useEffect(() => {
    var fileContent = JSON.parse(fs.readFileSync("./config.json"); // Reading from a JSON.
    var tempFilePaths = [];
    fileContent.FilePaths.forEach((file) => {
      tempFilePaths.push(file);
    });
    setFilePaths(tempFilePaths); // Contents of "config.js" is now in the "useState".
  }, []);

  return (
    <Child filePaths={filePaths}/>
  )
}
// Child.

export default function Child({filePaths}) {
  var links = [
    {
      path: filePaths[0].Link1,
    },
    {
      path: filePaths[0].Link2,
    },
  ]

  return (
    <div>Nothing here yet, but I would map those links to front-end links.</div>
  )
}
// config.json

{
  "url": "http:localhost:3000",
  "FilePaths": [
    {
      "Link1": "C:\Documents\Something",
      "Link2": "C:\Documents\SomethingElse"
    }
  ]
}

当我在 Child 组件的 return() 中呈现“filePaths”时,“filePaths”能够呈现,但我希望将“filePaths”设置为变量“links”。

我期望结果是什么?

我希望变量“links”在子组件中可以正常使用,能够在子组件中使用。

实际的结果是什么?结果如何?

启动应用程序时,我收到 TypeError:无法读取未定义的属性“0”。

我认为问题可能是什么?

我认为子组件在父组件未完成 useEffect() 的情况下进行渲染。我想知道是否有办法告诉子组件等待父组件完成,然后继续设置“links”变量。

3个回答

filePaths 将为 undefined ,因为您使用空输入调用 useState()

有两个选项(您可以选择一个)可以解决此问题:

  1. useState() 内初始化 filePaths

  2. 如果 filePaths 不为 null/undefined,则返回 Child 组件。

export default function Parent() {
    const [filePaths, setFilePaths] = useState();

    useEffect(() => {
        var fileContent = JSON.parse(fs.readFileSync("./config.json"); // Reading from a JSON.
        var tempFilePaths = [];
        fileContent.FilePaths.forEach((file) => {
            tempFilePaths.push(file);
        });
        setFilePaths(tempFilePaths); // Contents of "config.js" is now in the "useState".
    }, []);

    return (
        // return the Child component if the filePaths is not null/undefined
        {filePaths && <Child filePaths={filePaths}/>}
    )
}

我个人更喜欢第二个,因为当 filePaths 仍然为 null/undefined 时,我们可以添加加载组件。

Jabal Logian
2021-08-12

你说得对,这就是你应该更改子组件的原因。无论是否定义,它都会呈现 filePaths

尝试按如下方式操作。

export default function Child({filePaths}) {
  const [links, setLinks] = useState(filePaths);
  useEffect(()=>{
    setLinks(filePaths);
  },[filePaths])

  return (
    <div>Nothing here yet, but I would map those links to front-end links.</div>
  )
}
seagulls0125
2021-08-12

我认为你对方法调用顺序的猜测是正确的:

根据 这个 ,当你使用 useEffect 时,该方法会在渲染后被调用,就好像它是一个 componentDidMount 生命周期方法,它受到 React 官方生命周期图 React 文档 的支持。这就是因为 Child 组件内的 props.filePaths 未定义的原因。

为了避免这种情况,您应该尝试设置初始值(在 useState 方法中)。

类似于以下内容(可能将重复提取为函数):

// Parent.

export default function Parent() {

  var fileContent = JSON.parse(fs.readFileSync("./config.json"); // Reading from a JSON.
    var tempFilePaths = [];
    fileContent.FilePaths.forEach((file) => {
      tempFilePaths.push(file);
    });
  
  const [filePaths, setFilePaths] = useState(tempFilePaths);

  useEffect(() => {
    var fileContent = JSON.parse(fs.readFileSync("./config.json"); // Reading from a JSON.
    var tempFilePaths = [];
    fileContent.FilePaths.forEach((file) => {
      tempFilePaths.push(file);
    });
    setFilePaths(tempFilePaths); // Contents of "config.js" is now in the "useState".
  }, []);

  return (
    <Child filePaths={filePaths}/>
  )
}
Eduardo Agustín Rosselot
2021-08-12