Where can I make API call with hooks in react?

前端 未结 5 1342
有刺的猬
有刺的猬 2020-11-27 14:43

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

     componentDidMount(){
          //He         


        
5条回答
  •  感情败类
    2020-11-27 15:33

    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 (
        
    Name: {!firstName || !lastName ? 'Loading...' : `${firstName} ${lastName}`}
    ); } ReactDOM.render(, document.querySelector('#app'));
    
    
    
    

    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 (
        
    setId(e.target.value)}/>
    {JSON.stringify(todo, null, 2)}
    ); } ReactDOM.render(, document.querySelector('#app'));
    
    
    
    

    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!

提交回复
热议问题