如何在React应用中保持整个时间内状态不变?

huangapple go评论59阅读模式
英文:

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

问题

I understand your question. It seems like you want to fetch the profiles from the database once and use them throughout your React app without making redundant API calls. To achieve this, you can use a combination of Redux and React Router. Here's a suggested approach:

  1. Initialize the profiles data when your app loads in App.js by dispatching fetchAllProfiles action:
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchAllProfiles } from './yourActions';

function App() {
  const dispatch = useDispatch();
  const profiles = useSelector((state) => state.profileReducer.profiles);

  useEffect(() => {
    // Dispatch the action to fetch profiles only if it's empty
    if (profiles.length === 0) {
      dispatch(fetchAllProfiles());
    }
  }, [dispatch, profiles]);

  // Rest of your routes and components...
}
  1. Ensure that the fetchAllProfiles action fetches data only if the profiles array is empty or needs to be refreshed. Make sure the action returns a Promise and resolves when the data is fetched.

  2. In your reducer, update the state with the fetched profiles as you are currently doing.

By following this approach, you fetch the profiles data when the app loads, but subsequent visits to the /dashboard or other routes won't trigger redundant API calls if the data is already available in your Redux store.

Remember to handle loading and error states in your components, especially if the data fetching takes some time, to provide a better user experience.

英文:

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.

答案1

得分: 0

Redux提供了一个存储空间,您可以在其中存储数据,使其位于您的React应用程序之外,以便您可以从任何组件访问其内容。存储内容仅在分发操作时更改,因此切换到/dasboard路由不应影响您的Redux状态。

您的代码没有显示您如何尝试从存储中的profiles数组中获取数据,也许您的Dashboard组件中的方式或时间不正确,

const profiles = useSelector((state) => state.X.profiles); // X是您的combineReducers对象中profileReducer的键
英文:

Redux provides a store in which you can store data "outside" your React app so that you can access its content from any component.<br> 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) =&gt; state.X.profiles); // X is the key of of the profileReducer in the object of your combineReducers

huangapple
  • 本文由 发表于 2023年5月14日 12:01:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76245760.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定