reactjs 我的useEffect钩子从未被触发过,甚至在第一次加载时也是如此

e7arh2l6  于 2023-05-06  发布在  React
关注(0)|答案(2)|浏览(156)

我有一个问题,我的小React应用程序中的useEffect() React钩子从未被触发。
当应用加载时,它首先转到index.js,然后加载Dungeon组件。
所以它在这个意义上是有效的。
你可以看到我有console.log()调用,所以我可以看到什么被击中了,什么没有。
因此,应用程序在开始时加载查找,没有错误。
它确实加载了Dungeon组件,我看到预期的generationId被写入控制台。
API端点工作正常,因为我可以使用Postman成功测试它。
问题是,它永远不会命中API,因为getGeneration函数永远不会命中,因为useEffect永远不会被触发。
我得到的错误是:

Dungeon.js:15 Uncaught TypeError: Cannot read properties of undefined (reading 'data')

错误发生是因为data从未被API填充。
所以我知道为什么我会得到错误,但我不知道为什么useEffect没有被触发。
有没有人觉得有什么不对或不好的地方?
下面是我的index.js:

ReactDOM.render(
    <React.Fragment>
        <Dungeon generationId={id} />
    </React.Fragment>,
    document.getElementById('dungeon')
)

下面是Dungeon组件:

import React, { useState, useEffect } from "react";
import axios from 'axios';

const Dungeon = ({ generationId }) => {

    const [generationDetails, setGenerationDetails] = useState();
    console.log("Dungeon Component entry :: generationId has a value of --> ", generationId);

    const getGeneration = async (id) => {
        console.log("getGeneration hit.");
        const data = await axios.get('api/generations/' + id);
        setGenerationDetails(data);
    }

    useEffect(() => {
        console.log("useEffect() triggered..but it's never triggered! ");
        getGeneration(generationId);
    }, []) // Empty so it gets called only once
    return (
        <div id="generation">
            <div>
                <div id="generationDescription">
                    <div>Title:{generationDetails.data.title}</div>
                    <div>Description: {generationDetails.data.description}</div>
                </div>
            </div>
        </div>
    );
}

export default Dungeon;
6pp0gazn

6pp0gazn1#

您的错误似乎是在挂载组件(将其添加到DOM树)期间引起的,这发生在useEffect()运行之前。
对useEffect的第一次调用的状态与componentDidMount类似(后续调用与componentDidUpdate类似)。在您的示例中,安装组件包括显示标题和描述,而这些值取决于是否有从中获取它们的对象。
至少有三种可能的解决方案:
1.在useState()中添加一个默认对象。

const [generationDetails, setGenerationDetails] = useState({
  data: {
    description: '',
    title: 'Loading...',
  }
});

1.在呈现JSX之前测试对象是否已加载。

...

    return (
     {!!generationDetails && (
        <div id="generation">
            <div>
                <div id="generationDescription">
                    <div>Title:{generationDetails.data.title}</div>
                    <div>Description: {generationDetails.data.description}</div>
                </div>
            </div>
        </div>
     )
   });

1.对每个值使用可选的链接(Ossama也提到了)。在创建对象之前,表达式将返回undefined,并且undefined值不会渲染。

<div>Title:{generationDetails?.data?.title}</div>
<div>Description: {generationDetails?.data?.description}</div>
vh0rcniy

vh0rcniy2#

我建议你使用可选链接(?.)和默认值,例如,可以使用{generationDetails?.data?.title || ""}代替generationDetails.data.title

相关问题