Search code examples
reactjsredux

How can I keep the state unchanged for the entire time in React App?


I have a React App and I use Redux for state management. On my App.js I want to get some information from the database and use it on every page I have in my app. Only if there are changes to that array of course will everything will change accordingly, if some items are added or removed or updated.

But I want to use that array of object in my entire app so I don't have to call the backend in every page I am using that list (most of them). For example this is my App.js

function App() {

  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(fetchAllProfiles());
   }, [dispatch]);
  
  
  return (
    <Router>
      <Routes>
        <Route path='/' exact element={<Home/>} />
        <Route path="/auth" exact element={<Auth/>} />
        <Route path="/dashboard" exact element={<Dashboard />} />
        <Route path="/add-travel" exact element={<AddTravel />} />
        <Route path="/forgotpassword" exact element={<ForgotPassword />} />
        <Route path='/reset' exact element={<ResetPassword />} />
        <Route path="/profile" exact element={<Profile />} />
        <Route path="/myprofile" exact element={<MyProfile />} />
        <Route path="/add-location" exact element={<AddLocation />} />
        <Route path="/location" exact element={<Location />} />
        <Route path='/travel' exact element={<Travel />} />
        <Route path='/add-travel/draft/add-people' exact element={<AddPeople />} />
        <Route path='/add-travel/draft/add-waypoints' exact element={<AddWaypoints />} />
        <Route path='/add-travel/editwaypoint' exact element={<EditWaypoint />} />
        <Route path='/add-location/draft/add-people' exact element={<AddPeopleL />} />
        <Route path='/add-location/draft/add-events' exact element={<AddEvents />} />
        <Route path='/edit-location' exact element={<EditLocation />} />
        <Route path='/edit-location/timeline/people' exact element={<EditLocationPeople />} />
        <Route path='/edit-location/timeline/events' exact element={<EditLocationEvents />} />
        <Route path='/location/add-people' exact element = {<AddPeopleS />} />
        <Route path='/location/add-events' exact element = {<AddEventsS />} />
        <Route path='/edit-travel' exact element={<EditTravel />} />
        <Route path='/bibliography' exact element={<Bibliography />} />
        <Route path='/searchpage' exact element={<SearchPage />} />
        <Route path='/terms-and-conditions' exact element={<Terms/>} />
        <Route path='/edit-travel/add-people' exact element={<AddPeopleT/>} />
        <Route path='/edit-travel/add-waypoints' exact element={<AddWaypointsT />} />
        <Route path='/edit-travel/editwaypoint' exact element={<EditWaypointT/>} />
        <Route path='/howto' exact element={<HowTo />} /> 
        <Route path='/travel/waypoint' exact element={<Waypoint/>} />
        <Route path='/travel/person' exact element={<Person />} />
        
      </Routes>
    </Router>
  );
}

export default App;

bunch of routes. If a user is logged in, he is automatically redirected to /dashboard, where I use the profiles I get from backend by calling fetchAllProfiles.

This is my reducer for profiles:

const profileReducer = (state = {
    profiles: [],
    myProfile:null,
    profile: null,
  
}, action ) => {
    switch(action.type) {
        case FETCH_ALL_PROFILES:
           return {
            ...state, profiles: action.payload.profiles,
           } 
        default: return state; 
   }
}

export default profileReducer;

and this is used in a combineReducers. My index.js is looking like this

const store = createStore(reducers, compose(applyMiddleware(thunk)))
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
 
    <App />

  </Provider>
);

The problem is, I call the fetchAllProfiles when App.js is loading with the hope that one time it will be loaded from there and I can use it everywhere, but as soon as the page is changed and I am on /dashboard. The profiles array is empty.

I was trying to put it in the index.js but that didn't work either. I am asking for suggestions on how I can handle this. The array that is coming from database is more than 500 items long and it will be more. But I need all of them for what I am doing so I don't want to call that method in every page.


Solution

  • Redux provides a store in which you can store data "outside" your React app so that you can access its content from any component.
    The store content only changes when you dispatch actions, so switching the route to /dashboard should not affect your Redux state.

    Your code doesn't show how you are trying to get the profiles array, from the store, in your Dashboard component, maybe you are doing it the wrong way or at the wrong time,

    const profiles = useSelector((state) => state.X.profiles); // X is the key of of the profileReducer in the object of your combineReducers