【问题标题】:Reactjs useState hook not updating on promise dataReactjs useState 挂钩未更新承诺数据
【发布时间】:2021-03-30 07:49:15
【问题描述】:

我正在使用 react hook 而不是基于类的组件,但是当我从 graphql API 获取数据时它没有更新状态。

这里是我的代码:

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});


function EmpTable() {

  const [employee, setEmployee] = useState({});

    useEffect(() => {

        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              console.log(employee);
            });
    }, [])

    return (
        <div>return something</div>
    )
};


export default EmpTable;

当我打印employee 时,它只打印初始值。

但是当打印结果时,控制台会显示我从 API 获得的所有数据。

我让 useEffect 仅在页面/组件加载后运行,但它不起作用。

谁能帮我解决这个问题?

【问题讨论】:

标签: reactjs react-hooks apollo-client use-effect use-state


【解决方案1】:

还有另一种解决方案,您可以使用自定义挂钩在您想要使用的任何组件中使用您的返回值。

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});

const useCustomApi=()=>{
    const [employee, setEmployee] = useState({});
    useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              
            });
    }, [])


return employee;
}

function EmpTable() {

    const employee = useCustomApi();
    console.log(employee);

   return (
      <div>{JSON.stringify(employee,null,2)}</div>
   )
};


export default EmpTable;

【讨论】:

  • 你已经更新了你的第一个答案,你不需要发布另一个重复的答案。
  • @WilliamWang tnx 请注意,我以两种不同的方式回答,因为有两个问题,首先提问者想记录状态并且他在使用 useEffect 时遇到问题,其次他想返回状态,所以我认为有不同
【解决方案2】:

您需要使用 useEffect 钩子来实现这一点。

有关如何在反应钩子How to use `setState` callback on react hooks 上使用setState 回调的更多信息

你的代码应该是:

import React, { useEffect, useState } from 'react';
import client from '../gqlClient';
import { gql, ApolloClient, InMemoryCache  } from '@apollo/client';


const client = new ApolloClient({
  uri: 'http://localhost:8000/graphql/',
  cache: new InMemoryCache(),
});


function EmpTable() {

  const [employee, setEmployee] = useState({});

    useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              
            });
    }, [])

   useEffect(() => {
      console.log(employee);
   }, [employee]);

   return (
      <div>{JSON.stringify(employee,null,2)}</div>
   )
};


export default EmpTable;

【讨论】:

  • 我需要像你提到的那样使用两次useEffect吗?
  • 是的,因为它们的依赖关系不同。
  • 我明白了,但是当我使用两个 useEffect 时,它可以工作,问题是,我无法渲染数据,当我尝试返回以 html 渲染时,员工是空的,因为员工更新以后有什么解决办法?
  • 我在响应中添加了返回数据,但您应该知道 employee 是异步状态,它会在数据准备好时呈现数据。因此您应该在父组件中使用状态或将它们作为道具发送到另一个组件。此外还有一个名为 的组件,您可以等到加载它。
  • @pythonerdude 我为您的上一个问题添加了另一个解决方案。
【解决方案3】:

setEmployee 是异步方法,因此您无法在setEmployee 之后立即获取employee 的更新值。

setEmployee({result});
console.log(employee); // This will show the old `employee` value.

您应该通过添加 employee 依赖项在 useEffect 中获得更新的结果。

useEffect(() => {
        client
            .query({
                query: gql`
                query {
                  employees {
                    name
                  }
                }
                `
            })
            .then(result => {
              setEmployee({result});
              console.log(employee);
            });
}, [])

useEffect(() => {
  console.log(employee);
}, [employee]);

【讨论】:

  • 但问题是,当我让 useEffect 依赖于员工时,API 调用不断地获得千万次,它无限地调用 API 并没有停止,只是让我的浏览器崩溃了
  • 我说的是你需要在你的代码中再添加一个 useEffect
  • 如果在render中添加employee用法,只要setEmployee更新了employee值就会重新渲染。
  • 不,不行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 2021-06-06
  • 2021-05-13
  • 2020-05-31
  • 1970-01-01
  • 2021-09-04
相关资源
最近更新 更多