遇到问题时使用 useEffect 获取假 API 数据。

huangapple go评论58阅读模式
英文:

Facing problem when fetching data using a fake API using useEffect

问题

以下是代码部分的翻译:

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

const FetchData = () => {
  const [data, setData] = useState({})
  const [value, setValue] = useState(1)
  const [id, setId] = useState(1)
  const [loading, setLoading] = useState(true)

  const idUpdater = () => {
    setLoading(true)
    setId(value)
  }

  useEffect(() => {
    const fetchData = async () => {
       const data = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
       const response = await data.json()
       setData(response)
       setLoading(false)
    }
    setTimeout(fetchData, 2000)
  }, [id])

  return (
    <div>
      <input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
      <button onClick={idUpdater}>获取数据</button>
      {loading ? <h1>加载中...</h1> : <h1>{data.title}</h1>}
    </div>
  )
}

export default FetchData

请注意,代码部分已经翻译成中文。

英文:

I am a beginner in react and trying a basic example where I am fetching data based on what I am passing in input field , the value in input field goes as id to the API URL , Everything is working fine but
this fails for a particular case . Suppose I entered 3 in input field and then click the button , First time the data shows as expected , but if I again press the get data button the UI just stuck showing Loading...
I think it is related to dependency array in useEffect.

import React,{useState,useEffect} from &#39;react&#39;

const FetchData = () =&gt; {
  const [data,setData]=useState({})
  const [value,setValue]=useState(1)
  const [id,setId]=useState(1)
  const [loading,setLoading]=useState(true)

  const idUpdater=()=&gt;{
    setLoading(true)
    setId(value)
  }
  
  useEffect(()=&gt;{
    const fetchData= async()=&gt;{
       const data=await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
       const response=await data.json()
       setData(response)
       setLoading(false)
    }
    setTimeout(fetchData,2000)  
  },[id])

  
  
  return (

    &lt;div&gt;
    &lt;input type=&quot;text&quot; value={value} onChange={(e)=&gt;setValue(e.target.value)} /&gt;
    &lt;button onClick={idUpdater}&gt;Get Data&lt;/button&gt;
    {loading?&lt;h1&gt;Loading...&lt;/h1&gt;:&lt;h1&gt;{data.title}&lt;/h1&gt;}
    &lt;/div&gt;
  )
}

export default FetchData

I tried removing the dependency array , but it didn't work

答案1

得分: 0

根据您提供的条件,useEffect 中的代码仅在 id 不同的情况下才会被执行。当您再次按下按钮时,id 保持不变,因此useEffect 中的代码不会运行,并且在 idUpdater 中设置的 loading 状态将保持为 true。

更好的方法是在初始挂载时调用 fetch,并在按钮按下时重用该函数,如下所示:

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

const FetchData = () => {
  const [data, setData] = useState({});
  const [value, setValue] = useState(1);
  const [loading, setLoading] = useState(true);

  const idUpdater = () => {
    setLoading(true);
    fetchData(value);
  };

  const fetchData = async (pageNo) => {
    const data = await fetch(
      `https://jsonplaceholder.typicode.com/posts/${pageNo}`
    );
    const response = await data.json();
    setData(response);
    setLoading(false);
  };

  useEffect(() => {
    fetchData(1);
  }, []);

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
      <button onClick={idUpdater}>获取数据</button>
      {loading ? <h1>加载中...</h1> : <h1>{data.title}</h1>}
    </div>
  );
};

export default FetchData;

查看演示

英文:

Based on the condition you have given the code in useEffect gets only rendered when the id is different. When you press the button again the id remains same thus the code inside useEffect won't run and the loading state set in idUpdater will remain true.

A better approach to this would be calling fetch on initial mount and reusing that function on button press, as:

import React, { useState, useEffect } from &quot;react&quot;;

const FetchData = () =&gt; {
  const [data, setData] = useState({});
  const [value, setValue] = useState(1);
  const [loading, setLoading] = useState(true);

  const idUpdater = () =&gt; {
    setLoading(true);
    fetchData(value);
  };

  const fetchData = async (pageNo) =&gt; {
    const data = await fetch(
      `https://jsonplaceholder.typicode.com/posts/${pageNo}`
    );
    const response = await data.json();
    setData(response);
    setLoading(false);
  };

  useEffect(() =&gt; {
    fetchData(1);
  }, []);

  return (
    &lt;div&gt;
      &lt;input
        type=&quot;text&quot;
        value={value}
        onChange={(e) =&gt; setValue(e.target.value)}
      /&gt;
      &lt;button onClick={idUpdater}&gt;Get Data&lt;/button&gt;
      {loading ? &lt;h1&gt;Loading...&lt;/h1&gt; : &lt;h1&gt;{data.title}&lt;/h1&gt;}
    &lt;/div&gt;
  );
};

export default FetchData;

Check demo

答案2

得分: 0

      useEffect(() => {
        const fetchData = async () => {
          const data = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
          const response = await data.json()
          setData(response)
          setLoading(false)
        }
        setTimeout(fetchData, 2000)
      }, [id])

在方括号内的依赖项表示,每当 id 发生变化时,这个 useEffect 将被触发。

在你的情况下,当重新点击 "Get data" 按钮时,setLoading(true) 被调用,将你的界面置于 "Loading..." 状态,setId(value) 也被调用,但值没有改变(仍然是3),因此 useEffect 不会被触发。

英文:
  useEffect(()=&gt;{
    const fetchData= async()=&gt;{
       const data=await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
       const response=await data.json()
       setData(response)
       setLoading(false)
    }
    setTimeout(fetchData,2000)  
  },[id])

The dependencies inside the square brackets means, this useEffect will be triggered everytime the id changes.

In your case, when re-clicking the Get data button, setLoading(true) runs make your ui runs into Loading... state, the setId(value) also runs but the value does not change (still 3) therefore the useEffect is not triggered

huangapple
  • 本文由 发表于 2023年2月19日 21:17:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75500405.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定