【问题标题】: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])

标签: reactjs ajax graphql


【解决方案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) 可以拯救你,但正如我之前所说,它可能不是有效的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-13
        • 1970-01-01
        • 2018-11-16
        • 2019-08-09
        • 2020-07-05
        • 2020-01-12
        相关资源
        最近更新 更多