【问题标题】:How to use axios in Effect Hook?如何在 Effect Hook 中使用 axios?
【发布时间】:2019-04-08 18:47:17
【问题描述】:

在基于类的组件中:

componentDidMount() {
    axios.get('https://jsonplaceholder.typicode.com/posts').then((res) => {
        this.setState({
            posts: res.data.slice(0, 10)
        });
        console.log(posts);
    })
}

我试过这个:

const [posts, setPosts] = useState([]);

useEffect(() => {
    axios.get('https://jsonplaceholder.typicode.com/posts').then((res) => {
        setPosts(res.data.slice(0, 10));
        console.log(posts);
    })
});

它创建了一个无限循环。如果我将 []/{} 作为第二个参数 [1][2] 传递,那么它会阻止进一步的调用。但它也阻止了数组更新。

[1]Infinite loop in useEffect

[2]How to call loading function with React useEffect only once

【问题讨论】:

  • “如果我将[]/{} 作为第二个参数传递,那么它会阻止进一步调用”是什么意思。这就是你想要做的,只在初始渲染后运行给useEffect的函数。
  • 是的。我想运行一次该函数,因为它一次又一次地更新帖子数组。遵循您在其他帖子中提到的方法后,我得到了预期的“运行 useEffect 一次”,但我的帖子数组仍然是空的。不应该是 [post1, post2, ...]。
  • @Tholle 我接受了你的回答。

标签: reactjs axios react-hooks


【解决方案1】:

useEffect 提供一个空数组作为第二个参数,以表明您只希望效果在初始渲染后运行一次是可行的方法。 console.log(posts); 向您显示一个空数组的原因是因为 posts 变量仍然引用初始数组,而 setPosts 也是异步的,但如果在渲染中使用它仍然可以按您的意愿工作。

示例

const { useState, useEffect } = React;

function App() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    setTimeout(() => {
      setPosts([{ id: 0, content: "foo" }, { id: 1, content: "bar" }]);
      console.log(posts);
    }, 1000);
  }, []);

  return (
    <div>{posts.map(post => <div key={post.id}>{post.content}</div>)}</div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【讨论】:

    【解决方案2】:

    您可以查看axios-hooks 是如何实现的。

    它超级简单,使用您提供的配置对象(或 url)来决定何时发出请求,何时不发出请求,如 Tholle's answer 中所述。

    除了允许您在无状态功能组件中使用出色的 axios 之外,它还支持服务器端渲染,事实证明,钩子可以非常简单地实现。

    免责声明:我是该软件包的作者。

    【讨论】:

    • 这个包太棒了!虽然我想知道第一次调用 useAxios 时如何不发送请求?因为在提交表单之前你永远不会发布任何东西。
    • @Min 目前不支持它,但希望它很容易实现。你会在项目 github 页面上创建一个问题吗?也欢迎 PR :)
    【解决方案3】:

    我为 Axios.js 写了一个Custom Hooks

    这是一个例子:

    import React, { useState } from 'react';
    
    import useAxios from '@use-hooks/axios';
    
    export default function App() {
      const [gender, setGender] = useState('');
      const {
        response,
        loading,
        error,
        query,
      } = useAxios({
        url: `https://randomuser.me/api/${gender === 'unknow' ? 'unknow' : ''}`,
        method: 'GET',
        options: {
          params: { gender },
        },
        trigger: gender,
        filter: () => !!gender,
      });
    
      const { data } = response || {};
    
      const options = [
        { gender: 'female', title: 'Female' },
        { gender: 'male', title: 'Male' },
        { gender: 'unknow', title: 'Unknow' },
      ];
    
      if (loading) return 'loading...';
      return (
        <div>
          <h2>DEMO of <span style={{ color: '#F44336' }}>@use-hooks/axios</span></h2>
          {options.map(item => (
            <div key={item.gender}>
              <input
                type="radio"
                id={item.gender}
                value={item.gender}
                checked={gender === item.gender}
                onChange={e => setGender(e.target.value)}
              />
              {item.title}
            </div>
          ))}
          <button type="button" onClick={query}>Refresh</button>
          <div>
            {error ? error.message || 'error' : (
              <textarea cols="100" rows="30" defaultValue={JSON.stringify(data || {}, '', 2)} />
            )}
          </div>
        </div>
      );
    }
    

    你可以看到结果online

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2023-01-29
      • 2021-03-01
      • 2020-03-01
      • 1970-01-01
      • 2021-09-12
      相关资源
      最近更新 更多