首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >接口拉取时useEffect未被调用且未更新状态

接口拉取时useEffect未被调用且未更新状态
EN

Stack Overflow用户
提问于 2019-07-30 10:22:45
回答 3查看 24.7K关注 0票数 7

我使用useEffect钩子从well获取数据,并正确地声明了依赖关系。我的状态仍然没有被更新,因此我在渲染函数中得到了错误。我几乎尝试了所有的方法,从摆脱依赖数组到在依赖数组中声明multiples。我不知道我的函数出了什么问题。API的JSON响应格式如下:

代码语言:javascript
运行
复制
{
 location: {
 name: "Paris",
 region: "Ile-de-France",
 },
 current: {
  last_updated_epoch: 1564279222,
  last_updated: "2019-07-28 04:00",
  temp_c: 16,
  temp_f: 60.8,
  is_day: 0,
  condition: {
    text: "Clear",
    icon: "//cdn.apixu.com/weather/64x64/night/113.png",
    code: 1000
  },
  wind_mph: 6.9,
  wind_kph: 11.2
 }
}

下面是我的代码:

代码语言:javascript
运行
复制
const Weather = ({ capital }) => {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    console.log("useEffect called");
    const getWeather = async () => {
      try {
        const res = await axios.get(
          `http://api.apixu.com/v1/current.json?key=53d601eb03d1412c9c004840192807&q=${capital}`
        );
        setWeather(res.data);
      } catch (e) {
        console.log(e);
      }
    };
    getWeather();
  }, [capital]);
  console.log(weather);

  return (
    <Card style={{ width: "18rem", marginTop: "25px" }}>
      <Card.Img variant="top" src={weather.current.condition.icon} />

      <Card.Header style={{ textAlign: "center", fontSize: "25px" }}>
        Weather in {capital}
      </Card.Header>
    </Card>
  )
}

我希望看到图标的图像,但我在我的渲染函数中收到了以下错误消息:

代码语言:javascript
运行
复制
TypeError: Cannot read property 'current' of null
Weather
src/components/Weather.js:26
  23 | 
  24 | return (
  25 |   <Card style={{ width: "18rem", marginTop: "25px" }}>
  26 |     <Card.Img variant="top" src={weather.current.condition.icon} />
     | ^  27 | 
  28 |     <Card.Header style={{ textAlign: "center", fontSize: "25px" }}>
  29 |       Weather in {capital}

并且我的console.log(weather)返回null,即使它是在useEffect()之后调用的,并且console.log(useEffect called)根本没有记录,这意味着useEffect没有被调用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-07-30 10:28:20

错误消息告诉我们,Cannot read property 'current' of null,调用current的唯一位置是在Card.Imgweather.current中,因此我们推断weather在渲染过程中为null

发生这种情况的原因是因为api调用是异步的,它不会立即填充状态,所以渲染首先发生,并尝试从初始天气状态null读取.current

解决方案:在render方法中,确保在weathernull时不读取weather.current

例如,您可以使用{weather && <Card>...</Card}隐藏整个卡,直到加载数据并显示加载指示器,或者您可以使用src={weather && weather.current.condition.icon}作为快速解决方法。

代码语言:javascript
运行
复制
const Weather = ({capital}) => {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    console.log("useEffect called");
    const getWeather = async () => {
      try {
        const res = await axios.get(
          `http://api.apixu.com/v1/current.json?key=53d601eb03d1412c9c004840192807&q=${capital}`,
        );
        setWeather(res.data);
      } catch (e) {
        console.log(e);
      }
    };
    getWeather();
  }, [capital]);
  console.log(weather);

  return (
    <Card style={{width: "18rem", marginTop: "25px"}}>
      <Card.Img variant="top" src={weather && weather.current.condition.icon} />

      <Card.Header style={{textAlign: "center", fontSize: "25px"}}>
        Weather in {capital}
      </Card.Header>
    </Card>
  );
};
票数 15
EN

Stack Overflow用户

发布于 2020-10-02 02:02:09

所以,我遇到了一个类似的问题,useEffect钩子似乎根本没有被调用。相关的代码片段如下所示:

在我的功能组件中,代码的出现顺序如下:

  • 是一个变量钩子声明,应该由useEffect const facetFields = [];

中的AJAX调用来设置

使用AJAX在其中设置上述变量的

  • useEffect挂钩。

useEffect( ()=>{ console.log('FacetTreeView: useEffect entered');facetFields = getFacetFieldNames(props.tabIndex);},[]);

使用该变量的

  • JSX代码。

return ({ facetFields.map((facetLabel,索引) => { populateFacetInstances(facetLabel) }) } )

使用此代码,钩子中的控制台语句根本不会打印。另外,在渲染facetFields时,我一直收到一个未定义的错误。所以,原来useHook是在组件渲染后调用的。所以,在渲染过程中,变量facetFieldsundefined.So,我通过在我的JSX渲染部分代码中添加下面这一行来修复这个问题:

代码语言:javascript
运行
复制
facetFields && facetFields.map(.....

有一次,我做了上面的更改,控制开始转到hook.So,总而言之,如果在useEffect钩子中设置了任何代码,那么最好将JSX的执行推迟到钩子执行完成。虽然这不是强制性的,但它将使JSX代码更易于阅读。这可以通过使用布尔状态标志以一种简单的方式来实现。

  1. 定义状态:

const readyForRender,setReadyForRender = React.useState(false);2.在钩子中设置状态。

useEffect( ()=>{ console.log('FacetTreeView: useEffect entered');facetFields = getFacetFieldNames(props.tabIndex);setReadyForRender(true);},[]);

呈现JSX conditionally.的

索引if(readyForRender){

({ facetFields.map((facetLabel,readyForRender) => { populateFacetInstances(facetLabel) }) } );}否则{ return null;}

票数 2
EN

Stack Overflow用户

发布于 2021-07-08 00:23:34

有一次我遇到了同样令人费解的问题

在父代码中创建组件时,可以尝试在组件上添加关键道具

代码语言:javascript
运行
复制
<yourcomponent key="some_unique_value" />

这是因为在大多数情况下,当您的组件被重用时,根据它的创建方式,它通常会通过一些更改重新呈现它,而不是在您重用它时再次创建它,因此useEffect将不会被调用。例如在SwitchRoute中,循环,条件句...

因此,添加一个密钥可以防止这种情况发生。如果它在循环中,则需要确保每个元素都是唯一的,如果找不到更好的惟一键,可以在键中包含索引i

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57263525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档