简体   繁体   English

我在哪里可以使用钩子进行 API 调用?

[英]Where can I make API call with hooks in react?

Basically we do API calls in componentDidMount() life cycle method in React class components like below基本上我们在 React class 组件中的componentDidMount()生命周期方法中执行 API 调用,如下所示

     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但是在 React v16.7.0 中引入 hooks 后,它几乎都像函数组件一样

My query is, where exactly do we need to make API call in functional component with hooks?我的问题是,我们究竟需要在哪里使用钩子在功能组件中调用 API?

Do we have any method for it similar like componentDidMount() ?我们有没有类似componentDidMount()的方法?

Yes, there's a similar (but not the same!) substitute for componentDidMount with hooks, and it's the useEffect hook.是的,有一个类似的(但不一样!) componentDidMount的钩子替代品,它是useEffect钩子。

The other answers don't really answer your question about where you can make API calls.其他答案并没有真正回答您关于在哪里可以进行 API 调用的问题。 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() .您可以通过使用useEffect传入一个空数组或对象作为第二个参数来代替componentDidMount()来进行 API 调用。 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 .如果您不提供空数组或对象作为第二个参数,API 调用将在每次渲染时被调用,并且它实际上变成了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;传入一个空的输入数组 [] 告诉 React 你的效果不依赖于组件中的任何值,因此效果只会在挂载时运行并在卸载时清理; it won't run on updates.它不会在更新时运行。

Here are some examples for scenarios where you will need to make API calls:以下是需要进行 API 调用的场景的一些示例:

API Call Strictly on Mount严格在挂载上调用 API

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每当某些 Prop/State 更改时调用 API

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.例如,如果您要显示用户的个人资料页面,其中每个页面都有一个 userID state/prop,您应该将该 ID 作为值传递给useEffect的第二个参数,以便为新的用户 ID 重新获取数据。 componentDidMount is insufficient here as the component might not need remounting if you go directly from user A to user B's profile. componentDidMount在这里是不够的,因为如果您直接从用户 A 转到用户 B 的配置文件,则可能不需要重新安装组件。

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.例如,将 id 更改为 2 以查看useEffect再次运行。

 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.您应该阅读useEffect以便您知道可以/不能用它做什么。

Suspense悬念

As Dan Abramov said on this GitHub Issue :正如 Dan Abramov 在这个 GitHub 问题上所说:

Longer term we'll discourage this (useEffect) pattern because it encourages race conditions.从长远来看,我们将不鼓励这种 (useEffect) 模式,因为它鼓励竞争条件。 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相反,我们会推荐 Suspense 来获取数据

So stay tuned for Suspense!所以请继续关注悬疑!

You can use a library that provides the hooks for you like https://resthooks.io您可以使用为您提供挂钩的库,例如https://resthooks.io

Then getting your data becomes as simple as:然后获取您的数据变得如此简单:

const article = useSuspense(ArticleResource.detail(), { id });

Now you grabbed the article by id.现在你通过 id 抓取了这篇文章。 All non-happy paths (loading, error states) are handled by Suspense and Error boundaries respectively.所有不愉快的路径(加载、错误状态)分别由 Suspense 和Error 边界处理。

To get started follow this simple guide: https://resthooks.io/docs/getting-started/installation要开始遵循这个简单的指南: https ://resthooks.io/docs/getting-started/installation

At only 7kb gzipped this will save you a lot of pain and in the long run lower your bundle size due to less repeated code.压缩后只有 7kb,这将为您节省很多痛苦,并且从长远来看,由于重复代码较少,您的包大小会降低。

Demos演示

I am just posting this as a simpler way to understand acc.我只是将其发布为一种更简单的方式来理解 acc。 to my efforts.对我的努力。 Credit to Yangshun Tay's post that it covers almost everything.归功于 Yangshun Tay 的帖子,它几乎涵盖了所有内容。

API call on mounting of component安装组件的 API 调用

Code:代码:

  useEffect(() => { 
    // here is where you make API call(s) or any side effects
    fetchData('/data')
  }, [] ) /** passing empty brackets is necessary */

So using useEffect(fn,[]) with empty args as [] makes fn() triggered once throughout when component creates(mounts) and destroys(unmounts) without depending on any values.因此,使用带有空参数的useEffect(fn,[])作为[]会使fn()在组件创建(挂载)和销毁(卸载)时触发一次,而不依赖于任何值。

Pro tip:专家提示:

Also further if you return() something in this fn then it will act same as componentWillUnmount() lifecycle as that of class component.此外,如果您在此fnreturn()某些内容,那么它将与componentWillUnmount()生命周期相同,就像类组件的生命周期一样。

  useEffect(() => { 
   fetchData('/data')
   return () => {
    // this will be performed when component will unmount
    resetData()
   }
  }, [] )

API call when some value changes某些值更改时的 API 调用

If you are looking to call API when some value changes, simply pass that variable (which is storing value) into arguments array in useEffect() .如果您希望在某些值更改时调用 API,只需将该变量(存储值)传递到useEffect()中的参数数组中。

 useEffect(() => {
  // perform your API call here
  updateDetails();
 },[prop.name]) /** --> will be triggered whenever value of prop.name changes */

This will make sure that whenever value of prop.name changes, your function in hook gets triggered.这将确保每当prop.name的值发生变化时,您的钩子函数都会被触发。

Also to note : this hook will be also called initially when the component is mounted.还要注意:这个钩子也会在组件被安装时被调用。 So at that time your name value might be in initial state which is kind of unintended from your view.因此,那时您的 name 值可能处于初始状态,这在您看来是一种意外。 So you can add custom condition in your function to avoid unnecessary API calls.因此,您可以在函数中添加自定义条件以避免不必要的 API 调用。

When you are using functional components with the hooks API, you can use the useEffect() method to produce side effects.当您使用带有 hooks API 的功能组件时,您可以使用useEffect()方法来产生副作用。 Whenever the state is updated because of these side effects, the component will re-render.每当由于这些副作用而更新状态时,组件都会重新渲染。

Example from the docs.来自文档的示例。

import { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

For example, you could call setCount in a callback function of an async request.例如,您可以在异步请求的回调函数中调用setCount When the callback is executed, the state will get updated and React will re-render the component.当回调被执行时,状态将被更新,React 将重新渲染组件。 Also from the docs:同样来自文档:

Tip小费

If you're familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount , componentDidUpdate , and componentWillUnmount combined.如果你熟悉 React 类的生命周期方法,你可以将 useEffect Hook 看作componentDidMountcomponentDidUpdatecomponentWillUnmount的组合。

You could also use use-http like:你也可以使用use-http像:

import useFetch from 'use-http'

function App() {
  // add whatever other options you would add to `fetch` such as headers
  const options = {
    method: 'POST',
    body: {}, // whatever data you want to send
  }

  var [data, loading, error] = useFetch('https://example.com', options)

  // want to use object destructuring? You can do that too
  var { data, loading, error } = useFetch('https://example.com', options)

  if (error) {
    return 'Error!'
  }

  if (loading) {
    return 'Loading!'
  }

  return (
    <code>
      <pre>{data}</pre>
    </code>
  )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 React Hooks 在第二次渲染时调用 API - Make an API call on second render using React Hooks 如何在单击按钮时触发带有钩子和 Redux 的 API 调用 - How can i fire an API call with hooks and Redux on button click 如何使用反应钩子从第一个 api 调用结果中获取第二个 api 调用需要特定数据的序列 api 调用? - How to fetch sequence api calls where second api call need particular data from first api call result using react hooks? 如果发现更改,则挂钩依赖 API 调用 React - Hooks dependency API call if changes found React React 钩子上的无限调用 API 的问题 - Problem with infinite call API on React hooks 如何根据从第一次获得的值进行第二次 API 调用。 使用 React 和 useEffect 钩子 - How to Make A second API call based on the value gotten from the first. with React and useEffect hooks react hooks的逻辑在哪里? - Where is the logic of react hooks? 使用 react + hooks,我如何在异步 redux 正确调度后调用/使用“navigate()”? - Using react + hooks, how can i call/use "navigate()" after a async redux dispatch properly? 对 React Hooks 的 useFetch function 进行单个条件调用的正确方法? - Correct way to make single conditional call to React Hooks' useFetch function? 如何在 React 中使用钩子绑定函数? - How can I bind function with hooks in React?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM