【问题标题】:Reactjs using useState causing loop of axios requestsReactjs 使用 useState 导致 axios 请求循环
【发布时间】:2021-09-14 05:11:37
【问题描述】:

我正在开发一个 reactjs 应用程序。我正在尝试从 ajax 响应的数据中列出用户。下面是代码。

const [ users, setUsers ] = useState([]);
  useEffect(() => {
    const config = {
      headers: {
        Authorization: 'Bearer ' + localStorage.getItem('token')
      }
    }
    axios.get('users', config).then((res) => {
      if (res.status == 200 && res.data.msg == "success") {
        setUsers(res.data.users)
      }
      else {
        history.push("/");
      }

      feather.replace()
    });

  });

我正在使用下面的代码在表格中列出用户。

function getRows(users) {
    return users.map(user  => {
      const { u_id, username } = user;
      return (
        <tr key={u_id} id={u_id}>
          <td>{u_id}</td>
          <td>{username}</td>
          <td class="delete">
          <a href="javascript:void(0)"><span data-feather="edit"></span></a><a href="javascript:void(0)" onClick={(e) => deleteUser(e, u_id)}><span data-feather="trash"></span></a>
          </td>
        </tr>
      )
    });
  }

现在的问题是它正在生成一个无限循环的请求来获取用户。我认为这是因为每次状态更改时都会调用 useEffect 钩子。如何解决这个问题。

【问题讨论】:

  • useeffect 的末尾使用空白数组,所以它看起来像},[] )
  • @CodeBug 酷!。工作!
  • @Akhilesh 您必须使用空数组作为第二个参数来停止对组件更新的触发效果。这是一篇关于 useEffect 和数据获取的有用文章robinwieruch.de/react-hooks-fetch-data
  • useEffect without dependency = 在每次渲染上运行效果。 useEffect with empty [] dependency = 只运行一次效果。 useEffect 与依赖 [some_state] = 对每个 some_state 更改运行效果。
  • 将添加答案,请将其标记为已接受。

标签: javascript reactjs


【解决方案1】:
 useEffect(() => {
const config = {
  headers: {
    Authorization: 'Bearer ' + localStorage.getItem('token')
  }
}
axios.get('users', config).then((res) => {
  if (res.status == 200 && res.data.msg == "success") {
    setUsers(res.data.users)
  }
  else {
    history.push("/");
  }

  feather.replace()
  });
}, []); 

注意这里我传递了空的 array[] 作为 useEffect 的第二个参数,

useEffect 出现空数组的原因

如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉 React 你的效果不依赖于任何来自 props 或 state 的值,所以它永远不需要重新运行。这不是作为特殊情况处理的——它直接遵循依赖项数组的工作方式。

阅读更多关于useEffect

【讨论】:

    【解决方案2】:

    您希望添加一个空数组作为useEffect 依赖项,因此它只运行一次:

    useEffect(() => {
      const config = {
        headers: {
          Authorization: "Bearer " + localStorage.getItem("token"),
        },
      };
      axios.get("users", config).then((res) => {
        if (res.status == 200 && res.data.msg == "success") {
          setUsers(res.data.users);
        } else {
          history.push("/");
        }
    
        feather.replace();
      });
    }, []);  //<-- Add empty dependency here
    

    【讨论】:

      【解决方案3】:

      useEffect 钩子基本上接受两个参数,第一个是回调,第二个是依赖数组(可选)。第二个参数(依赖数组)的目的是在依赖数组中的任何值发生变化时触发回调函数。因此,如果您不在 useEffect 钩子中使用依赖项数组,则每次渲染组件时都会执行回调函数,即每当状态变量发生变化时。

      那么是什么导致了循环?

      const [ users, setUsers ] = useState([]);
        useEffect(() => {
          const config = {
            headers: {
              Authorization: 'Bearer ' + localStorage.getItem('token')
            }
          }
          axios.get('users', config).then((res) => {
            if (res.status == 200 && res.data.msg == "success") {
              setUsers(res.data.users) //Updating state causes the component to re-render
            }
            else {
              history.push("/");
            }
      
            feather.replace()
          });
      
        });
      

      查看您的代码,我们可以观察到您正在使用两个钩子(useStateuseEffect),因此当 promise 得到解决时,您正在使用最新获取的信息更新您的 users 状态。到现在为止还挺好。当状态更新时,我们知道组件会重新渲染(这是 React 工作的基本原理)。因此更新users 状态会导致组件函数重新渲染,这将再次调用useEffect,而useEffect 将再次更新users 状态,依此类推。

      解决方法

      为了避免这个循环,我们希望只执行一次 useEffect,而不是每次渲染组件时。这可以通过传递一个空数组作为第二个参数来完成(这基本上告诉 React 仅在第一次渲染组件时运行`useEffect`)。
      const [ users, setUsers ] = useState([]);
        useEffect(() => {
          const config = {
            headers: {
              Authorization: 'Bearer ' + localStorage.getItem('token')
            }
          }
          axios.get('users', config).then((res) => {
            if (res.status == 200 && res.data.msg == "success") {
              setUsers(res.data.users) //Updating state causes the component to re-render
            }
            else {
              history.push("/");
            }
      
            feather.replace()
          });
      
        },[]); //Empty array as the second argument
      

      在使用基于类的组件时,这类似于componentDidMount。 此外,您还可以将变量添加到数组中,这将导致 useEffect 仅在数组中的变量发生突变时才被调用。

      【讨论】:

        【解决方案4】:

        依赖数组添加到你的useEffect钩子中,这将解决你的问题

        这就像组件挂载了一样

        useEffect(()=> {
         /// you're code    
        } , []) 
        

        但是您使用的那个就像组件确实更新并导致问题,因为您只需要在组件安装时执行代码

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-10-18
          • 1970-01-01
          • 2020-06-07
          • 1970-01-01
          • 1970-01-01
          • 2019-05-20
          • 1970-01-01
          • 2021-10-21
          相关资源
          最近更新 更多