score:2

Accepted answer

Use a separate variable like a simple count mechanism:

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

<button onClick={() => setCount(count + 1)} />

Then use 'count' as the stateful variable, as well as the url (if the user searched for something different):

useEffect(() => {
  const fetchData = async () => {
    const result = await axios(url);
    setData(result.data);
  };

  fetchData();
}, [url, count]);

score:0

I think the flow you describe could be simplified if, after making your initial api request, an action is dispatched to fetch the latest data that's available. Subsequently, the request should be made every time the component mounts, that way your component is not responsible for making sure it has the most updated data. This flow would look something like:

1) GET list

2) enter new item, save

3) make POST request

4) have an operation (outside of the consuming component) handle the response, and if it's successful, dispatch an action to refire the initial GET list call and if not, a call to handle the error.

score:2

Here is a different approach. Maybe there is a better way but in this situation, it seems working.

You can return fetchData from the useDataApi and then use it in the onClick handler and look for the URL change by the help of useRef. In order to do that you should move fetchData outside of the useEffect and wrap it with useCallback

  ...
  const fetchData = useCallback(
    async () => {
      setIsError(false);
      setIsLoading(true);

      try {
        const result = await axios(url);
        setData(result.data);
      } catch (error) {
        setIsError(true);
      }

      setIsLoading(false);
    },
    [url],
  );


  useEffect(() => {
    fetchData();
  }, [url, fetchData]); // add fetchData here as a second dependency

  return [{ data, isLoading, isError }, setUrl, fetchData]; // add fetchData here as the third returned variable.
};

Then in your App you can use refs to check if the URL is not changed:

function App() {
  const [query, setQuery] = useState('redux');
  const latestQuery = useRef(query); // define the ref
  const [{ data, isLoading, isError }, doFetch, fetchData] = useDataApi(
    'https://hn.algolia.com/api/v1/search?query=redux',
    { hits: [] },
  );

  return (
    <Fragment>
      <form
        onSubmit={event => {
          // check the query change
          if (latestQuery.current === query) {
            fetchData();
          }
          doFetch(
            `https://hn.algolia.com/api/v1/search?query=${query}`,
          );

          // set current query to the ref value
          latestQuery.current = query;

          event.preventDefault();
        }}
      >
      .....

I'm not quite sure this is a better solution since I'm still learning the hooks myself, too :)


Related Query

More Query from same tag