获取请求后无法更新状态

Posted

技术标签:

【中文标题】获取请求后无法更新状态【英文标题】:Can't Update state after fetch request 【发布时间】:2022-01-20 23:22:22 【问题描述】:

我正在尝试制作一个应用程序,从 Graphql API 获取数据,并在获取后更新状态,但在成功请求后我获取了数据,但我无法使用该数据更新状态。当我控制台记录响应数据时,它会显示包含所需数据的数组,但是当我更新状态并控制台记录状态时,它会显示空数组。

我需要更新状态以在组件中使用它,当我这样做时会抛出 currList 未定义的错误。

这里是代码和控制台的图片。

export default function App() 
  const [search, setSeach] = useState("");
  const [currList, setCurrList] = useState([]);

  const fetchShips = async () => 
    const response = await request(gql`
      
        ships 
          name
          home_port
          image
        
      
    `);
    console.log("request response", response.data);
    setCurrList(response.data);
    console.log("currlist:", currList);
  ;

  useEffect(() => 
    fetchShips();
  , [currList]);

  const Searchitems = (event) => 
    setSeach(event.target.value);
    setCurrList(
      currList.filter((item) => 
        return item.name.includes(search) || item.home_port.includes(search);
      )
    );
  ;

  return (
    <div className="App">
      <div className="container">
        <header></header>
        <div className="body">
          <input
            type="text"
            id="search"
            value=search
            onChange=Searchitems
            className="input"
            placeholder="Search Ships"
          />
          <p>Total Count: currList.length</p>
          <div className="ships">
            currList.map((item, index) => 
              return (
                <Ship
                  key=index
                  name=item.name
                  port=item.port
                  img=item.image
                />
              );
            )
          </div>
        </div>
      </div>
    </div>
  );

【问题讨论】:

已设置,但 setCurrList 是异步的,您可以通过将其记录到 useEffect 中来查看 currList 状态 尝试登录到useEffect useEffect(()=&gt; console.log(currList),[currList]) 【参考方案1】:

状态只是在代码运行时更新,这就是它记录状态为空数组的原因,尝试再次控制台记录它,您会看到列表中有一些东西。

【讨论】:

【参考方案2】:

这很正常,一切都是异步发生的。一旦您的 currList 更新,React 将触发重新渲染,您将获得它的新值。如果你想听这个变化,你必须使用 useEffect 和 currList 作为依赖。

useEffect(() => 
    console.log("List is updated", currList);
, [currList]);

【讨论】:

我需要状态来渲染组件,我该怎么做?当我使用上面的代码时,它会抛出错误“currList.map 不是函数”和“无法读取未定义(长度)的属性”。? 首先,关于您共享的代码,useEffect 应该有一个空数组作为依赖项,因为您只想为第一次渲染调用 fetchShips useEffect(() => fetchShips(); , []); 在搜索输入中输入之后或之前是否看到错误? 我在输入搜索输入之前看到错误,该错误显示在组件渲染中 你能看到这一行执行了吗:console.log("request response", response.data); ?控制台中显示了什么?【参考方案3】:

函数 fetchShips 对特定渲染调用的 currList 状态变量有闭包,因此当您在调用 setCurrList 后记录它时,它会显示之前的状态而不是更新的状态,您可以将其记录在 useEffect 中以查看更改.

【讨论】:

【参考方案4】:

我曾经遇到过同样的问题。我找不到有效的解决方案,但我的解决方案还是救了我。

我使用了 useRef 而不是 useState。 试试这个:

  const currList = useRef([]);

useEffect=(()=>
const fetchShips = async () => 
    const response = await request(gql`
      
        ships 
          name
          home_port
          image
        
      
    `);
    console.log("request response", response.data);
     // setCurrList(response.data);
if(response)
    currlist.current = response.data

    console.log("currlist:", currList);
  ;
fetchShips()
// Also as far as I know ,you should use useEffect like this
,[])
//... codes

return(
//... codes
 currList.current.map(...

)
//... codes

在使用 useRef 之前,请尝试在 useEffect 中定义您的 fetchShips 函数,这样也许您不需要我的解决方案。

为什么我的解决方案对您的情况无效? 当您想要更新您的 currList 数据时,useRef 不会触发重新渲染。即使您的数据已更新,您也无法在屏幕上看到它。 所以 setCurrList(currList.current) 可以拯救你,但正如我之前所说,它可能不是有效的方法。

【讨论】:

以上是关于获取请求后无法更新状态的主要内容,如果未能解决你的问题,请参考以下文章

无法获取更新的道具/状态

ReactJS - 更新后子级无法访问父级状态

为啥即使在有状态小部件中使用 setstate 也无法获取更新的变量。因为我想在新的 TabBar 选项上更新我的 Container

在亚马逊 MWS 中更新订单状态后出现“无法履行订单”错误

更新状态超过 1 次后调用函数

如何在db更新后获取SQLAlchemy ORM对象的先前状态?