admin管理员组

文章数量:1402955

How a fetch should be performed in react hooks? Among these two code snippets, which one is called a best practice or a best react pattern to perform a fetch?

This example is using useEffect to perform a fetch operation.

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

export default function App() {
  const [query, setQuery] = useState("");
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);

  useEffect(() => {
    if (!loading) return;
    const fetchData = async () => {
      const response = await fetch(
        `=${query}`
      );
      const data = await response.json();
      setData(data.items);
      setLoading(false);
    };
    fetchData();
  }, [loading, query]);

  const onSubmit = e => {
    e.preventDefault();
    setLoading(true);
  };

  return (
    <div className="App">
      <h1>Search Github Repo.</h1>
      <h3>Implementation One</h3>
      <form onSubmit={onSubmit}>
        <input
          type="text"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
        <button type="submit">Search</button>
      </form>
      {loading && <div>Loading...</div>}
      {!loading &&
        data.map(repo => (
          <div key={repo.id}>
            <h4>{repo.name}</h4>
            <p>{repo.description}</p>
          </div>
        ))}
    </div>
  );
}

This example is using the onClick event handler to perform a fetch operation.

import React, { useState } from "react";

export default function App() {
  const [query, setQuery] = useState("");
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);

  const onSubmit = e => {
    e.preventDefault();
    setLoading(true);
    const fetchData = async () => {
      const response = await fetch(
        `=${query}`
      );
      const data = await response.json();
      setData(data.items);
      setLoading(false);
    };
    fetchData();
  };

  return (
    <div className="App">
      <h1>Search Github Repo.</h1>
      <h3>Implementation Two</h3>
      <form onSubmit={onSubmit}>
        <input
          type="text"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
        <button type="submit">Search</button>
      </form>
      {loading && <div>Loading...</div>}
      {!loading &&
        data.map(repo => (
          <div key={repo.id}>
            <h4>{repo.name}</h4>
            <p>{repo.description}</p>
          </div>
        ))}
    </div>
  );
}

Running example in codesandbox

How a fetch should be performed in react hooks? Among these two code snippets, which one is called a best practice or a best react pattern to perform a fetch?

This example is using useEffect to perform a fetch operation.

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

export default function App() {
  const [query, setQuery] = useState("");
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);

  useEffect(() => {
    if (!loading) return;
    const fetchData = async () => {
      const response = await fetch(
        `https://api.github./search/repositories?q=${query}`
      );
      const data = await response.json();
      setData(data.items);
      setLoading(false);
    };
    fetchData();
  }, [loading, query]);

  const onSubmit = e => {
    e.preventDefault();
    setLoading(true);
  };

  return (
    <div className="App">
      <h1>Search Github Repo.</h1>
      <h3>Implementation One</h3>
      <form onSubmit={onSubmit}>
        <input
          type="text"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
        <button type="submit">Search</button>
      </form>
      {loading && <div>Loading...</div>}
      {!loading &&
        data.map(repo => (
          <div key={repo.id}>
            <h4>{repo.name}</h4>
            <p>{repo.description}</p>
          </div>
        ))}
    </div>
  );
}

This example is using the onClick event handler to perform a fetch operation.

import React, { useState } from "react";

export default function App() {
  const [query, setQuery] = useState("");
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);

  const onSubmit = e => {
    e.preventDefault();
    setLoading(true);
    const fetchData = async () => {
      const response = await fetch(
        `https://api.github./search/repositories?q=${query}`
      );
      const data = await response.json();
      setData(data.items);
      setLoading(false);
    };
    fetchData();
  };

  return (
    <div className="App">
      <h1>Search Github Repo.</h1>
      <h3>Implementation Two</h3>
      <form onSubmit={onSubmit}>
        <input
          type="text"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
        <button type="submit">Search</button>
      </form>
      {loading && <div>Loading...</div>}
      {!loading &&
        data.map(repo => (
          <div key={repo.id}>
            <h4>{repo.name}</h4>
            <p>{repo.description}</p>
          </div>
        ))}
    </div>
  );
}

Running example in codesandbox

Share Improve this question edited Jun 29, 2020 at 2:39 Sachin Bhandari asked Jun 9, 2020 at 7:13 Sachin BhandariSachin Bhandari 5664 silver badges19 bronze badges 4
  • I don't understand the question? it depends entirely on how your application requires. if you need the data on load use useEffect for hooks or ponentDidMount for classes. if you only need it on button click then call it when you click a button like you have done – Red Baron Commented Jun 9, 2020 at 7:17
  • As per my understanding in your case, you should use useEffect, because with this you always have correct query state – Harsh kurra Commented Jun 9, 2020 at 7:20
  • @RedBaron, Is it good to perform actions after the UI state has been changed on performing an action. As that would be a reactive way to do it or it is not? – Sachin Bhandari Commented Jun 9, 2020 at 7:53
  • you should use Shubham's answer, that makes sense – Red Baron Commented Jun 9, 2020 at 7:54
Add a ment  | 

2 Answers 2

Reset to default 8

It depend on your usecase as to which method you should take

fetching data in useEffect is useful in following scenarios

  • Fetching data during some lifecycles like initial render
  • Fetching data when some prop changes
  • fetching data in an interval but setting up a subscription or setInterval

Fetching data in handler is useful in below scenario

  • Based on a user interaction such as search button click, search input change

Since your case is a based on a use interaction its better and more controlled to actually call the API in a handler instead of a useEffect hook

I would say you should go with the hooks implementation. It's remended in the React docs for performing side effects:

Data fetching, setting up a subscription, and manually changing the DOM in React ponents are all examples of side effects. Whether or not you’re used to calling these operations “side effects” (or just “effects”), you’ve likely performed them in your ponents before. (link to the quote)

There is one more consideration to think about. In your hook implementation:

useEffect(() => {
    if (!loading) return;
    const fetchData = async () => {
      const response = await fetch(
        `https://api.github./search/repositories?q=${query}`
      );
      const data = await response.json();
      setData(data.items);
      setLoading(false);
    };
    fetchData();
  }, [loading, query]);

you used an optimization. You're passing [loading, query] into your hook, which means the function will run only when one of those values change. In your second implementation you will have your fetch running on every single input change

Here's a link to the React docs about this aspect of hooks.

本文标签: javascriptFetch data from an api in useEffect or in event handler directly in reactStack Overflow