我在哪里可以使用钩子进行 API 调用以进行反应? [英] Where can I make API call with hooks in react?

查看:36
本文介绍了我在哪里可以使用钩子进行 API 调用以进行反应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上我们在 React 类组件中的 componentDidMount() 生命周期方法中调用 API,如下所示

 componentDidMount(){//这里我们做API调用并相应地做setState}

但是在 React v16.7.0 引入 hooks 之后,基本上都是函数式组件

我的问题是,我们究竟需要在哪些地方使用钩子在功能组件中进行 API 调用?

我们有类似componentDidMount()的方法吗?

解决方案

是的,有一个类似(但不一样!)的带有钩子的 componentDidMount 替代品,它是 useEffect 钩子.

其他答案并没有真正回答您关于可以在何处进行 API 调用的问题.您可以通过使用 useEffect传入一个空数组或对象作为第二个参数来代替 componentDidMount() 来进行 API 调用.这里的关键是第二个参数.如果您不提供空数组或对象作为第二个参数,API 调用将在每次渲染时调用,它实际上变成了 componentDidUpdate.

如文档中所述:

<块引用>

传入一个空数组 [] 的输入告诉 React 你的 effect 不依赖于来自组件的任何值,所以该 effect 只会在挂载时运行并在卸载时清理;它不会在更新时运行.

以下是一些需要进行 API 调用的场景示例:

在挂载时严格调用 API

尝试运行下面的代码并查看结果.

function User() {const [firstName, setFirstName] = React.useState(null);const [lastName, setLastName] = React.useState(null);React.useEffect(() => {fetch('https://randomuser.me/api/').then(results => results.json()).then(数据=> {const {name} = data.results[0];setFirstName(name.first);setLastName(name.last);});}, []);//<-- 这里必须传入[]!返回 (<div>姓名:{!firstName ||!姓 ?正在加载...":`${firstName} ${lastName}`}

);}ReactDOM.render(, document.querySelector('#app'));

<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script><div id="app"></div>

每当某些 Prop/State 发生变化时调用 API

例如,如果您要显示用户的个人资料页面,其中每个页面都有一个 userID state/prop,则应将该 ID 作为值传递给 useEffect 的第二个参数,以便将重新获取新用户 ID 的数据.componentDidMount 在这里是不够的,因为如果您直接从用户 A 转到用户 B 的配置文件,则该组件可能不需要重新安装.

在传统的类中,你会这样做:

componentDidMount() {this.fetchData();}componentDidUpdate(prevProps, prevState) {if (prevState.id !== this.state.id) {this.fetchData();}}

使用钩子,那就是:

useEffect(() => {this.fetchData();}, [ID]);

尝试运行下面的代码并查看结果.例如,将 id 更改为 2 以查看 useEffect 再次运行.

function Todo() {const [todo, setTodo] = React.useState(null);const [id, setId] = React.useState(1);React.useEffect(() => {if (id == null || id === '') {返回;}获取(`https://jsonplaceholder.typicode.com/todos/${id}`).then(results => results.json()).then(数据=> {setTodo(数据);});}, [ID]);//useEffect 将在 id 不同时触发.返回 (<div><输入值={id} onChange={e =>setId(e.target.value)}/><br/><pre>{JSON.stringify(todo, null, 2)}</pre>

);}ReactDOM.render(, document.querySelector('#app'));

<script src="https://unpkg.com/react@16.8.1/umd/react.development.js"></脚本><script src="https://unpkg.com/react-dom@16.8.1/umd/react-dom.development.js"></script><div id="app"></div>

你应该阅读 useEffect 所以你知道你能/不能用它做什么.

悬念

正如 Dan Abramov 在这个 GitHub 问题上所说:

<块引用>

从长远来看,我们将不鼓励这种 (useEffect) 模式,因为它鼓励竞争条件.比如——在你的通话开始和结束之间可能会发生任何事情,你可能会得到新的道具.相反,我们会推荐使用 Suspense 来获取数据

敬请期待悬疑!

Basically we do API calls in componentDidMount() life cycle method in React class components like below

     componentDidMount(){
          //Here we do API call and do setState accordingly
     }

But after hooks are introduced in React v16.7.0, its all like functional components mostly

My query is, where exactly do we need to make API call in functional component with hooks?

Do we have any method for it similar like componentDidMount()?

解决方案

Yes, there's a similar (but not the same!) substitute for componentDidMount with hooks, and it's the useEffect hook.

The other answers don't really answer your question about where you can make API calls. You can make API calls by using useEffect and passing in an empty array or object as the second argument as a replacement for componentDidMount(). The key here is the second argument. If you don't provide an empty array or object as the second argument, the API call will be called on every render, and it effectively becomes a componentDidUpdate.

As mentioned in the docs:

Passing in an empty array [] of inputs tells React that your effect doesn’t depend on any values from the component, so that effect would run only on mount and clean up on unmount; it won’t run on updates.

Here are some examples for scenarios where you will need to make API calls:

API Call Strictly on Mount

Try running the code below and see the result.

function User() {
  const [firstName, setFirstName] = React.useState(null);
  const [lastName, setLastName] = React.useState(null);
  
  React.useEffect(() => {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        const {name} = data.results[0];
        setFirstName(name.first);
        setLastName(name.last);
      });
  }, []); // <-- Have to pass in [] here!

  return (
    <div>
      Name: {!firstName || !lastName ? 'Loading...' : `${firstName} ${lastName}`}
    </div>
  );
}

ReactDOM.render(<User />, document.querySelector('#app'));

<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

API Call Whenever Some Prop/State Changes

If you are for example displaying a profile page of a user where each page has a userID state/prop, you should pass in that ID as a value into the second parameter of useEffect so that the data will be refetched for a new user ID. componentDidMount is insufficient here as the component might not need remounting if you go directly from user A to user B's profile.

In the traditional classes way, you would do:

componentDidMount() {
  this.fetchData();
}

componentDidUpdate(prevProps, prevState) {
  if (prevState.id !== this.state.id) {
    this.fetchData();
  }
}

With hooks, that would be:

useEffect(() => {
  this.fetchData();
}, [id]);

Try running the code below and see the result. Change the id to 2 for instance to see that useEffect is run again.

function Todo() {
  const [todo, setTodo] = React.useState(null);
  const [id, setId] = React.useState(1);
  
  React.useEffect(() => {
    if (id == null || id === '') {
      return;
    }
    
    fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
      .then(results => results.json())
      .then(data => {
        setTodo(data);
      });
  }, [id]); // useEffect will trigger whenever id is different.

  return (
    <div>
      <input value={id} onChange={e => setId(e.target.value)}/>
      <br/>
      <pre>{JSON.stringify(todo, null, 2)}</pre>
    </div>
  );
}

ReactDOM.render(<Todo />, document.querySelector('#app'));

<script src="https://unpkg.com/react@16.8.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.8.1/umd/react-dom.development.js"></script>

<div id="app"></div>

You should read up on useEffect so that you know what you can/cannot do with it.

Suspense

As Dan Abramov said on this GitHub Issue:

Longer term we'll discourage this (useEffect) pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching

So stay tuned for Suspense!

这篇关于我在哪里可以使用钩子进行 API 调用以进行反应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆