How to fetch data only once and never again in reacthooks and redux

Viewed 2917

Please how do you I fetch data only once and never again when moving forth and back in react components using React Hooks. I simply want it on such a way that once the data is fetched for the first time in the component, it should not fetch again. Using an empty array [ ] in react hooks will make the component to fetch data once every single time we move to the component again. This is a sample code used in reacthooks to fetch the data only once. I simply want to fetch the data once and not again even when transitioning from page/component to component. This two links only fetch data once when navigating between pages. Thanks and hope to hear from you all http://www.favesound.de/ http://soundredux.io/

useEffect(() => {
const fetchData = async () => {
const result = await axios(url);
setData(result.data);
};
fetchData();
}, [url]);
4 Answers

Set the redux store data as null or some empty value. Before making the request, check if you store has already data. This will make sure only one request.

import React from "react";
import { useDispatch, useSelector } from "react-redux";

const Component = () => {
  const dispatch = useDispatch();
  const data = useSelector((state) => state.data);
};

useEffect(() => {
  if (data === null) {
    const fetchData = async () => {
      const result = await axios(url);
      dispatch({ type: "update-data", payload: result.data });
    };
    fetchData();
  }
}, [data]);

You can save the result into a variable outside of your compoment :

let DATA;

function App() {
  const [data, setData] = useState(DATA)

  useEffect(() => {
    if (DATA !== undefined) {
      return;
    }

    (async () => {
      const result = await axios(url);
      DATA = result.data;
      setData(DATA);
    })();
  }, []);

  ....
}

I didn't see any relation with redux in your code. If you are using redux, you can fetch the data outside of a component (in your the file where you are creating the store for example) and then dispatch an action containing the fetched data, so the data will be fetched only once.

const store = createStore(...)

(async () => {
   const result = await axios(url);
   store.dispatch({ type: 'INIT_DATA_FETCHED', payload: result.data });
})();

If I understand correctly, you want the useEffect callback only fires once on the first render.

To achieve that behaviour, you can pass an empty array to the second argument of useEffect() like so:

const fetchData = async () => {
const result = await axios(url);
setData(result.data);
};
fetchData();
}, []); /* <-- do this */```

I faced the same problem: When I dispatch action into the "Todos" component where I showed todos. And when I uploaded my todos in the state in another "AddTodos" component, "Todos" component was not updated, because in "Todos" dispatch(fetchData()); was updated state from API.

Todos component:

useEffect(() => {
 dispatch(fetchData());
}, []);

Instead you need to try to dispatch your fetchData() at the top level into index.js

store.dispatch(fetchData());

Like:

Index.js

const store = createStore(
    rootReducer,
    compose(
        applyMiddleware(thunk),
        /* preloadedState, */
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
);
store.dispatch(fetchData());

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <Router>
                <App />
            </Router>
        </Provider>
    </React.StrictMode>,
    document.getElementById('root')
);

Here is explained and have an example. https://redux.js.org/tutorials/fundamentals/part-6-async-logic#fetching-todos-from-a-server

Related