React Hooks - Making an Ajax request











up vote
4
down vote

favorite
3












I have just began playing around with React hooks and am wondering how an A request should look?



I have tried many attempts, but am unable to get it to work, and also don't really know the best way to implement it. Below is my latest attempt:



import React, { useState, useEffect } from 'react';

const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({})

useEffect(() => {
const resp = fetch(URL).then(res => {
console.log(res)
})
});
return (
<div>
// display content here
</div>
)
}









share|improve this question




















  • 2




    "I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
    – Alex Wayne
    Oct 30 at 7:14















up vote
4
down vote

favorite
3












I have just began playing around with React hooks and am wondering how an A request should look?



I have tried many attempts, but am unable to get it to work, and also don't really know the best way to implement it. Below is my latest attempt:



import React, { useState, useEffect } from 'react';

const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({})

useEffect(() => {
const resp = fetch(URL).then(res => {
console.log(res)
})
});
return (
<div>
// display content here
</div>
)
}









share|improve this question




















  • 2




    "I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
    – Alex Wayne
    Oct 30 at 7:14













up vote
4
down vote

favorite
3









up vote
4
down vote

favorite
3






3





I have just began playing around with React hooks and am wondering how an A request should look?



I have tried many attempts, but am unable to get it to work, and also don't really know the best way to implement it. Below is my latest attempt:



import React, { useState, useEffect } from 'react';

const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({})

useEffect(() => {
const resp = fetch(URL).then(res => {
console.log(res)
})
});
return (
<div>
// display content here
</div>
)
}









share|improve this question















I have just began playing around with React hooks and am wondering how an A request should look?



I have tried many attempts, but am unable to get it to work, and also don't really know the best way to implement it. Below is my latest attempt:



import React, { useState, useEffect } from 'react';

const App = () => {
const URL = 'http://api.com';
const [data, setData] = useState({})

useEffect(() => {
const resp = fetch(URL).then(res => {
console.log(res)
})
});
return (
<div>
// display content here
</div>
)
}






javascript reactjs react-hooks






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 6:08









Yangshun Tay

8,22953565




8,22953565










asked Oct 30 at 7:09









peter flanagan

6781932




6781932








  • 2




    "I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
    – Alex Wayne
    Oct 30 at 7:14














  • 2




    "I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
    – Alex Wayne
    Oct 30 at 7:14








2




2




"I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
– Alex Wayne
Oct 30 at 7:14




"I have tried many attempts" What did you try? "am unable to get it to work" What happened instead of what you expected?
– Alex Wayne
Oct 30 at 7:14












5 Answers
5






active

oldest

votes

















up vote
8
down vote













You can make a function called useFetch that will implement useEffect. This will trigger the lifecycle hooks on componentDidMount and the componentDidUpdate. A function passed to useEffect will run after the render is committed to the screen.



Here is a demo in code sandbox.



See code below.



import React, { useState, useEffect } from "react"

const useFetch = (url, defaultData) => {
const [data, updateData] = useState(defaultData)

useEffect(async () => {
const resp = await fetch(url)
const json = await resp.json()
updateData(json)
}, [url])

return data
}

const App = () => {
const URL = 'http://www.example.json';
const result = useFetch(url, {})

return (
<div>
{JSON.stringify(result)}
</div>
)
}





share|improve this answer






























    up vote
    2
    down vote













    Works just fine... Here you go:



    import React, { useState, useEffect } from 'react';

    const useFetch = url => {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(async () => {
    const response = await fetch(url);
    const data = await response.json();
    const [item] = data.results;
    setData(item);
    setLoading(false);
    }, );

    return { data, loading };
    };

    export default () => {
    const { data, loading } = useFetch('https://api.randomuser.me/');

    return (
    <div>
    {loading ? (
    <div>...loading</div>
    ) : (
    <div>
    {data.name.first} {data.name.last}
    </div>
    )}
    </div>
    );
    };


    Live Demo






    share|improve this answer























    • Simple and clear.
      – varun raja
      Nov 6 at 2:38


















    up vote
    2
    down vote













    Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.



    function useTriggerableEndpoint(fn) {
    const [res, setRes] = useState({ data: null, error: null, loading: null });
    const [req, setReq] = useState();

    useEffect(
    async () => {
    if (!req) return;
    try {
    setRes({ data: null, error: null, loading: true });
    const { data } = await axios(req);
    setRes({ data, error: null, loading: false });
    } catch (error) {
    setRes({ data: null, error, loading: false });
    }
    },
    [req]
    );

    return [res, (...args) => setReq(fn(...args))];
    }


    You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).



    const todosApi = "https://jsonplaceholder.typicode.com/todos";

    function postTodoEndpoint() {
    return useTriggerableEndpoint(data => ({
    url: todosApi,
    method: "POST",
    data
    }));
    }


    Finally, from within your function component



    const [newTodo, postNewTodo] = postTodoEndpoint();

    function createTodo(title, body, userId) {
    postNewTodo({
    title,
    body,
    userId
    });
    }


    And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.






    share|improve this answer






























      up vote
      0
      down vote













      Here's something which I think will work:



      import React, { useState, useEffect } from 'react';

      const App = () => {
      const URL = 'http://api.com';
      const [data, setData] = useState({})

      useEffect(async () => {
      const resp = await fetch(URL);
      const data = await resp.json();

      setData(data);
      }, );

      return (
      <div>
      { data.something ? data.something : 'still loading' }
      </div>
      )
      }


      There are couple of important bits:




      • The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".

      • Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.






      share|improve this answer




























        up vote
        0
        down vote













        Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.



        With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.



        Here's an example which fetches a random user profile from an API and renders the name.






        function AjaxExample() {
        const [user, setUser] = React.useState(null);
        React.useEffect(() => {
        fetch('https://randomuser.me/api/')
        .then(results => results.json())
        .then(data => {
        setUser(data.results[0]);
        });
        }, ); // Pass empty array to only run once on mount.

        return <div>
        {user ? user.name.first : 'Loading...'}
        </div>;
        }

        ReactDOM.render(<AjaxExample/>, document.getElementById('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>








        share|improve this answer





















          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53059059%2freact-hooks-making-an-ajax-request%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          5 Answers
          5






          active

          oldest

          votes








          5 Answers
          5






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          8
          down vote













          You can make a function called useFetch that will implement useEffect. This will trigger the lifecycle hooks on componentDidMount and the componentDidUpdate. A function passed to useEffect will run after the render is committed to the screen.



          Here is a demo in code sandbox.



          See code below.



          import React, { useState, useEffect } from "react"

          const useFetch = (url, defaultData) => {
          const [data, updateData] = useState(defaultData)

          useEffect(async () => {
          const resp = await fetch(url)
          const json = await resp.json()
          updateData(json)
          }, [url])

          return data
          }

          const App = () => {
          const URL = 'http://www.example.json';
          const result = useFetch(url, {})

          return (
          <div>
          {JSON.stringify(result)}
          </div>
          )
          }





          share|improve this answer



























            up vote
            8
            down vote













            You can make a function called useFetch that will implement useEffect. This will trigger the lifecycle hooks on componentDidMount and the componentDidUpdate. A function passed to useEffect will run after the render is committed to the screen.



            Here is a demo in code sandbox.



            See code below.



            import React, { useState, useEffect } from "react"

            const useFetch = (url, defaultData) => {
            const [data, updateData] = useState(defaultData)

            useEffect(async () => {
            const resp = await fetch(url)
            const json = await resp.json()
            updateData(json)
            }, [url])

            return data
            }

            const App = () => {
            const URL = 'http://www.example.json';
            const result = useFetch(url, {})

            return (
            <div>
            {JSON.stringify(result)}
            </div>
            )
            }





            share|improve this answer

























              up vote
              8
              down vote










              up vote
              8
              down vote









              You can make a function called useFetch that will implement useEffect. This will trigger the lifecycle hooks on componentDidMount and the componentDidUpdate. A function passed to useEffect will run after the render is committed to the screen.



              Here is a demo in code sandbox.



              See code below.



              import React, { useState, useEffect } from "react"

              const useFetch = (url, defaultData) => {
              const [data, updateData] = useState(defaultData)

              useEffect(async () => {
              const resp = await fetch(url)
              const json = await resp.json()
              updateData(json)
              }, [url])

              return data
              }

              const App = () => {
              const URL = 'http://www.example.json';
              const result = useFetch(url, {})

              return (
              <div>
              {JSON.stringify(result)}
              </div>
              )
              }





              share|improve this answer














              You can make a function called useFetch that will implement useEffect. This will trigger the lifecycle hooks on componentDidMount and the componentDidUpdate. A function passed to useEffect will run after the render is committed to the screen.



              Here is a demo in code sandbox.



              See code below.



              import React, { useState, useEffect } from "react"

              const useFetch = (url, defaultData) => {
              const [data, updateData] = useState(defaultData)

              useEffect(async () => {
              const resp = await fetch(url)
              const json = await resp.json()
              updateData(json)
              }, [url])

              return data
              }

              const App = () => {
              const URL = 'http://www.example.json';
              const result = useFetch(url, {})

              return (
              <div>
              {JSON.stringify(result)}
              </div>
              )
              }






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 8 at 11:07

























              answered Oct 30 at 7:16









              Paul Fitzgerald

              5,1821633




              5,1821633
























                  up vote
                  2
                  down vote













                  Works just fine... Here you go:



                  import React, { useState, useEffect } from 'react';

                  const useFetch = url => {
                  const [data, setData] = useState(null);
                  const [loading, setLoading] = useState(true);

                  useEffect(async () => {
                  const response = await fetch(url);
                  const data = await response.json();
                  const [item] = data.results;
                  setData(item);
                  setLoading(false);
                  }, );

                  return { data, loading };
                  };

                  export default () => {
                  const { data, loading } = useFetch('https://api.randomuser.me/');

                  return (
                  <div>
                  {loading ? (
                  <div>...loading</div>
                  ) : (
                  <div>
                  {data.name.first} {data.name.last}
                  </div>
                  )}
                  </div>
                  );
                  };


                  Live Demo






                  share|improve this answer























                  • Simple and clear.
                    – varun raja
                    Nov 6 at 2:38















                  up vote
                  2
                  down vote













                  Works just fine... Here you go:



                  import React, { useState, useEffect } from 'react';

                  const useFetch = url => {
                  const [data, setData] = useState(null);
                  const [loading, setLoading] = useState(true);

                  useEffect(async () => {
                  const response = await fetch(url);
                  const data = await response.json();
                  const [item] = data.results;
                  setData(item);
                  setLoading(false);
                  }, );

                  return { data, loading };
                  };

                  export default () => {
                  const { data, loading } = useFetch('https://api.randomuser.me/');

                  return (
                  <div>
                  {loading ? (
                  <div>...loading</div>
                  ) : (
                  <div>
                  {data.name.first} {data.name.last}
                  </div>
                  )}
                  </div>
                  );
                  };


                  Live Demo






                  share|improve this answer























                  • Simple and clear.
                    – varun raja
                    Nov 6 at 2:38













                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  Works just fine... Here you go:



                  import React, { useState, useEffect } from 'react';

                  const useFetch = url => {
                  const [data, setData] = useState(null);
                  const [loading, setLoading] = useState(true);

                  useEffect(async () => {
                  const response = await fetch(url);
                  const data = await response.json();
                  const [item] = data.results;
                  setData(item);
                  setLoading(false);
                  }, );

                  return { data, loading };
                  };

                  export default () => {
                  const { data, loading } = useFetch('https://api.randomuser.me/');

                  return (
                  <div>
                  {loading ? (
                  <div>...loading</div>
                  ) : (
                  <div>
                  {data.name.first} {data.name.last}
                  </div>
                  )}
                  </div>
                  );
                  };


                  Live Demo






                  share|improve this answer














                  Works just fine... Here you go:



                  import React, { useState, useEffect } from 'react';

                  const useFetch = url => {
                  const [data, setData] = useState(null);
                  const [loading, setLoading] = useState(true);

                  useEffect(async () => {
                  const response = await fetch(url);
                  const data = await response.json();
                  const [item] = data.results;
                  setData(item);
                  setLoading(false);
                  }, );

                  return { data, loading };
                  };

                  export default () => {
                  const { data, loading } = useFetch('https://api.randomuser.me/');

                  return (
                  <div>
                  {loading ? (
                  <div>...loading</div>
                  ) : (
                  <div>
                  {data.name.first} {data.name.last}
                  </div>
                  )}
                  </div>
                  );
                  };


                  Live Demo







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Oct 30 at 7:28

























                  answered Oct 30 at 7:20









                  SakoBu

                  788317




                  788317












                  • Simple and clear.
                    – varun raja
                    Nov 6 at 2:38


















                  • Simple and clear.
                    – varun raja
                    Nov 6 at 2:38
















                  Simple and clear.
                  – varun raja
                  Nov 6 at 2:38




                  Simple and clear.
                  – varun raja
                  Nov 6 at 2:38










                  up vote
                  2
                  down vote













                  Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.



                  function useTriggerableEndpoint(fn) {
                  const [res, setRes] = useState({ data: null, error: null, loading: null });
                  const [req, setReq] = useState();

                  useEffect(
                  async () => {
                  if (!req) return;
                  try {
                  setRes({ data: null, error: null, loading: true });
                  const { data } = await axios(req);
                  setRes({ data, error: null, loading: false });
                  } catch (error) {
                  setRes({ data: null, error, loading: false });
                  }
                  },
                  [req]
                  );

                  return [res, (...args) => setReq(fn(...args))];
                  }


                  You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).



                  const todosApi = "https://jsonplaceholder.typicode.com/todos";

                  function postTodoEndpoint() {
                  return useTriggerableEndpoint(data => ({
                  url: todosApi,
                  method: "POST",
                  data
                  }));
                  }


                  Finally, from within your function component



                  const [newTodo, postNewTodo] = postTodoEndpoint();

                  function createTodo(title, body, userId) {
                  postNewTodo({
                  title,
                  body,
                  userId
                  });
                  }


                  And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.






                  share|improve this answer



























                    up vote
                    2
                    down vote













                    Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.



                    function useTriggerableEndpoint(fn) {
                    const [res, setRes] = useState({ data: null, error: null, loading: null });
                    const [req, setReq] = useState();

                    useEffect(
                    async () => {
                    if (!req) return;
                    try {
                    setRes({ data: null, error: null, loading: true });
                    const { data } = await axios(req);
                    setRes({ data, error: null, loading: false });
                    } catch (error) {
                    setRes({ data: null, error, loading: false });
                    }
                    },
                    [req]
                    );

                    return [res, (...args) => setReq(fn(...args))];
                    }


                    You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).



                    const todosApi = "https://jsonplaceholder.typicode.com/todos";

                    function postTodoEndpoint() {
                    return useTriggerableEndpoint(data => ({
                    url: todosApi,
                    method: "POST",
                    data
                    }));
                    }


                    Finally, from within your function component



                    const [newTodo, postNewTodo] = postTodoEndpoint();

                    function createTodo(title, body, userId) {
                    postNewTodo({
                    title,
                    body,
                    userId
                    });
                    }


                    And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.






                    share|improve this answer

























                      up vote
                      2
                      down vote










                      up vote
                      2
                      down vote









                      Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.



                      function useTriggerableEndpoint(fn) {
                      const [res, setRes] = useState({ data: null, error: null, loading: null });
                      const [req, setReq] = useState();

                      useEffect(
                      async () => {
                      if (!req) return;
                      try {
                      setRes({ data: null, error: null, loading: true });
                      const { data } = await axios(req);
                      setRes({ data, error: null, loading: false });
                      } catch (error) {
                      setRes({ data: null, error, loading: false });
                      }
                      },
                      [req]
                      );

                      return [res, (...args) => setReq(fn(...args))];
                      }


                      You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).



                      const todosApi = "https://jsonplaceholder.typicode.com/todos";

                      function postTodoEndpoint() {
                      return useTriggerableEndpoint(data => ({
                      url: todosApi,
                      method: "POST",
                      data
                      }));
                      }


                      Finally, from within your function component



                      const [newTodo, postNewTodo] = postTodoEndpoint();

                      function createTodo(title, body, userId) {
                      postNewTodo({
                      title,
                      body,
                      userId
                      });
                      }


                      And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.






                      share|improve this answer














                      Great answers so far, but I'll add a custom hook for when you want to trigger a request, because you can do that too.



                      function useTriggerableEndpoint(fn) {
                      const [res, setRes] = useState({ data: null, error: null, loading: null });
                      const [req, setReq] = useState();

                      useEffect(
                      async () => {
                      if (!req) return;
                      try {
                      setRes({ data: null, error: null, loading: true });
                      const { data } = await axios(req);
                      setRes({ data, error: null, loading: false });
                      } catch (error) {
                      setRes({ data: null, error, loading: false });
                      }
                      },
                      [req]
                      );

                      return [res, (...args) => setReq(fn(...args))];
                      }


                      You can create a function using this hook for a specific API method like so if you wish, but be aware that this abstraction isn't strictly required and can be quite dangerous (a loose function with a hook is not a good idea in case it is used outside of the context of a React component function).



                      const todosApi = "https://jsonplaceholder.typicode.com/todos";

                      function postTodoEndpoint() {
                      return useTriggerableEndpoint(data => ({
                      url: todosApi,
                      method: "POST",
                      data
                      }));
                      }


                      Finally, from within your function component



                      const [newTodo, postNewTodo] = postTodoEndpoint();

                      function createTodo(title, body, userId) {
                      postNewTodo({
                      title,
                      body,
                      userId
                      });
                      }


                      And then just point createTodo to an onSubmit or onClick handler. newTodo will have your data, loading and error statuses. Sandbox code right here.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 9 at 15:15









                      cwharris

                      14.9k43455




                      14.9k43455










                      answered Oct 31 at 3:22









                      horyd

                      1,038911




                      1,038911






















                          up vote
                          0
                          down vote













                          Here's something which I think will work:



                          import React, { useState, useEffect } from 'react';

                          const App = () => {
                          const URL = 'http://api.com';
                          const [data, setData] = useState({})

                          useEffect(async () => {
                          const resp = await fetch(URL);
                          const data = await resp.json();

                          setData(data);
                          }, );

                          return (
                          <div>
                          { data.something ? data.something : 'still loading' }
                          </div>
                          )
                          }


                          There are couple of important bits:




                          • The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".

                          • Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.






                          share|improve this answer

























                            up vote
                            0
                            down vote













                            Here's something which I think will work:



                            import React, { useState, useEffect } from 'react';

                            const App = () => {
                            const URL = 'http://api.com';
                            const [data, setData] = useState({})

                            useEffect(async () => {
                            const resp = await fetch(URL);
                            const data = await resp.json();

                            setData(data);
                            }, );

                            return (
                            <div>
                            { data.something ? data.something : 'still loading' }
                            </div>
                            )
                            }


                            There are couple of important bits:




                            • The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".

                            • Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.






                            share|improve this answer























                              up vote
                              0
                              down vote










                              up vote
                              0
                              down vote









                              Here's something which I think will work:



                              import React, { useState, useEffect } from 'react';

                              const App = () => {
                              const URL = 'http://api.com';
                              const [data, setData] = useState({})

                              useEffect(async () => {
                              const resp = await fetch(URL);
                              const data = await resp.json();

                              setData(data);
                              }, );

                              return (
                              <div>
                              { data.something ? data.something : 'still loading' }
                              </div>
                              )
                              }


                              There are couple of important bits:




                              • The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".

                              • Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.






                              share|improve this answer












                              Here's something which I think will work:



                              import React, { useState, useEffect } from 'react';

                              const App = () => {
                              const URL = 'http://api.com';
                              const [data, setData] = useState({})

                              useEffect(async () => {
                              const resp = await fetch(URL);
                              const data = await resp.json();

                              setData(data);
                              }, );

                              return (
                              <div>
                              { data.something ? data.something : 'still loading' }
                              </div>
                              )
                              }


                              There are couple of important bits:




                              • The function that you pass to useEffect acts as a componentDidMount which means that it may be executed many times. That's why we are adding an empty array as a second argument, which means "This effect has no dependencies, so run it only once".

                              • Your App component still renders something even tho the data is not here yet. So you have to handle the case where the data is not loaded but the component is rendered. There's no change in that by the way. We are doing that even now.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 8 at 10:37









                              Krasimir

                              11.1k22545




                              11.1k22545






















                                  up vote
                                  0
                                  down vote













                                  Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.



                                  With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.



                                  Here's an example which fetches a random user profile from an API and renders the name.






                                  function AjaxExample() {
                                  const [user, setUser] = React.useState(null);
                                  React.useEffect(() => {
                                  fetch('https://randomuser.me/api/')
                                  .then(results => results.json())
                                  .then(data => {
                                  setUser(data.results[0]);
                                  });
                                  }, ); // Pass empty array to only run once on mount.

                                  return <div>
                                  {user ? user.name.first : 'Loading...'}
                                  </div>;
                                  }

                                  ReactDOM.render(<AjaxExample/>, document.getElementById('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>








                                  share|improve this answer

























                                    up vote
                                    0
                                    down vote













                                    Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.



                                    With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.



                                    Here's an example which fetches a random user profile from an API and renders the name.






                                    function AjaxExample() {
                                    const [user, setUser] = React.useState(null);
                                    React.useEffect(() => {
                                    fetch('https://randomuser.me/api/')
                                    .then(results => results.json())
                                    .then(data => {
                                    setUser(data.results[0]);
                                    });
                                    }, ); // Pass empty array to only run once on mount.

                                    return <div>
                                    {user ? user.name.first : 'Loading...'}
                                    </div>;
                                    }

                                    ReactDOM.render(<AjaxExample/>, document.getElementById('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>








                                    share|improve this answer























                                      up vote
                                      0
                                      down vote










                                      up vote
                                      0
                                      down vote









                                      Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.



                                      With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.



                                      Here's an example which fetches a random user profile from an API and renders the name.






                                      function AjaxExample() {
                                      const [user, setUser] = React.useState(null);
                                      React.useEffect(() => {
                                      fetch('https://randomuser.me/api/')
                                      .then(results => results.json())
                                      .then(data => {
                                      setUser(data.results[0]);
                                      });
                                      }, ); // Pass empty array to only run once on mount.

                                      return <div>
                                      {user ? user.name.first : 'Loading...'}
                                      </div>;
                                      }

                                      ReactDOM.render(<AjaxExample/>, document.getElementById('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>








                                      share|improve this answer












                                      Traditionally, you would write the Ajax call in the componentDidMount lifecycle of class components and use setState to display the returned data when the request has returned.



                                      With hooks, you would use useEffect and passing in an empty array as the second argument to make the callback run once on mount of the component.



                                      Here's an example which fetches a random user profile from an API and renders the name.






                                      function AjaxExample() {
                                      const [user, setUser] = React.useState(null);
                                      React.useEffect(() => {
                                      fetch('https://randomuser.me/api/')
                                      .then(results => results.json())
                                      .then(data => {
                                      setUser(data.results[0]);
                                      });
                                      }, ); // Pass empty array to only run once on mount.

                                      return <div>
                                      {user ? user.name.first : 'Loading...'}
                                      </div>;
                                      }

                                      ReactDOM.render(<AjaxExample/>, document.getElementById('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>








                                      function AjaxExample() {
                                      const [user, setUser] = React.useState(null);
                                      React.useEffect(() => {
                                      fetch('https://randomuser.me/api/')
                                      .then(results => results.json())
                                      .then(data => {
                                      setUser(data.results[0]);
                                      });
                                      }, ); // Pass empty array to only run once on mount.

                                      return <div>
                                      {user ? user.name.first : 'Loading...'}
                                      </div>;
                                      }

                                      ReactDOM.render(<AjaxExample/>, document.getElementById('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>





                                      function AjaxExample() {
                                      const [user, setUser] = React.useState(null);
                                      React.useEffect(() => {
                                      fetch('https://randomuser.me/api/')
                                      .then(results => results.json())
                                      .then(data => {
                                      setUser(data.results[0]);
                                      });
                                      }, ); // Pass empty array to only run once on mount.

                                      return <div>
                                      {user ? user.name.first : 'Loading...'}
                                      </div>;
                                      }

                                      ReactDOM.render(<AjaxExample/>, document.getElementById('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>






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Nov 11 at 6:07









                                      Yangshun Tay

                                      8,22953565




                                      8,22953565






























                                           

                                          draft saved


                                          draft discarded



















































                                           


                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53059059%2freact-hooks-making-an-ajax-request%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          Full-time equivalent

                                          Bicuculline

                                          さくらももこ