【问题标题】:React-router-DOM is refreshing my context stateReact-router-DOM 正在刷新我的上下文状态
【发布时间】:2023-02-24 10:12:24
【问题描述】:

我已经查找了几个小时,但找不到解决问题的方法。

我正在开发一个使用 react context 的应用程序,我还使用 react-router-dom 来浏览我的页面。

这个上下文文件有一个初始状态,因为我正在使用 useReducer 钩子来改变它。 但是当我浏览应用程序时,比如更改或切换页面,我的状态会重新加载,除非我发出新的获取请求,否则我无法从我的状态获取数据。

我在某处读到 react-router-dom 正在刷新我的页面,所以我无法做到。

你们有什么提示可以给我吗?

实际上我想不出解决方案,因为我对如何使状态“永久”感到困惑

有我的指数:

import React from "react";
import ReactDOM from "react-dom";

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AppProvider } from "./context";
import "./styles.css";
import Login from "./pages/Login";
import Profile from "./pages/Profile";
import Register from "./pages/Register";
import FriendshipAccess from "./pages/FriendshipAccess";
import SearchPage from "./pages/SearchPage";
import EditAccount from "./pages/EditAccount";

ReactDOM.render(
  <React.StrictMode>
    <AppProvider>
      <BrowserRouter>
        <Routes>
          <Route exact path="/" element={<Login />} />
          <Route path="/profile" element={<Profile />} />
          <Route path="/account/edit" element={<EditAccount />} />
          <Route path="/register" element={<Register />} />
          <Route path="/users/:nickname" element={<FriendshipAccess />} />
          <Route path="/users/search" element={<SearchPage />} />
        </Routes>
      </BrowserRouter>
    </AppProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

这是我的背景:

import React, { useContext, useReducer } from "react";
import reducer from "./reducer";
import {
  registerNewUser,
  authUser, //MARKDOWN OF THE TASK!!!!!
  getUserPosts,
  accessUserProfile,
  validateUserToken,
  editAccountData,
} from "./operations/operations";

const AppContext = React.createContext();

const initialState = {
  userState: {
    userData: {},
    userPosts: [],
  },
  serverMessages: {},
  accessToken: false,
  accessedUserPage: {
    userData: {},
    userPosts: {},
  },
};

const AppProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const registerSubmitHandler = async (userInputs) => {
    const registeredUser = await registerNewUser(userInputs);
    dispatch({ type: "REGISTER_USER", payload: registeredUser.data });
  };

  const authUserCredentials = async (userCredentials) => {
    const userDataFromDb = await authUser(userCredentials);
    localStorage.setItem("access_token", userDataFromDb.token);
    dispatch({
      type: "AUTH_USER",
      payload: userDataFromDb,
    });
  };

  const getUserDataByToken = async (token) => {
    const userDataFromDb = await validateUserToken(token);
    dispatch({ type: "LOGGED_GET_DATA", payload: userDataFromDb });
  };

  const editUserAccount = async (token, accountData) => {
    const editedUserData = await editAccountData(token, accountData);
    dispatch({ type: "EDIT_USER_ACCOUNT", payload: editedUserData });
  };

  const getUserPostsData = async (token) => {
    const postsDataFromDb = await getUserPosts(token);
    dispatch({ type: "FETCH_USER_POSTS", payload: postsDataFromDb });
  };

  const getBuddyData = async (nicknameParam) => {
    const userDataFromDb = await accessUserProfile(nicknameParam);
    dispatch({ type: "ACCESS_FRIEND_PAGE", payload: userDataFromDb });
  };

  const userLogout = async () => {
    await localStorage.removeItem("access_token");
    const emptyState = {
      ...state,
      userState: {
        userData: "",
        userPosts: "",
      },
    };
    dispatch({ type: "USER_LOGOUT", payload: emptyState });
  };

  return (
    <AppContext.Provider
      value={{
        ...state,
        registerSubmitHandler,
        authUserCredentials,
        getUserPostsData,
        userLogout,
        getBuddyData,
        getUserDataByToken,
        editUserAccount,
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

export const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppProvider, AppContext };

【问题讨论】:

  • AppProvider在ReactTree中位于BrowserRouter之上,所以切换路由应该不会影响它。您能否更详细地阐明状态重置或重新加载的确切含义?您如何浏览应用程序?
  • 所以,我的初始状态,在我的 context.js 文件的顶部返回一个空对象。当我登录、关注新用户、发布内容等时,它会从我的数据库中返回数据。但是如果我切换页面,它只会返回到初始的空状态,除非我每次都在必要时从我的数据库中请求数据
  • 你是如何切换页面的?
  • 在必要的页面上,我没有使用“a”元素,而是使用从 react router dom 导入的“Link”元素
  • 如果您手动更新地址栏中的 URL 或使用原始锚点 (&lt;a&gt;) 标记这将重新加载页面,应用程序将以初始状态重新加载 (除非你是坚持状态).使用 Link 组件不应该这样做。你可以edit 分享使用的链接吗?

标签: reactjs react-hooks react-router-dom react-context react-state


【解决方案1】:

我没有看到您的代码有什么奇怪的地方。

尽管如此,最好的做法是将您的上下文值封装在备忘录中。如果你不这样做,所有使用这个上下文的组件都会比它们需要的渲染次数更多。

你能试试吗?

const AppProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const value = React.useMemo(() => {
    const registerSubmitHandler = async (userInputs) => {
      const registeredUser = await registerNewUser(userInputs);
      dispatch({ type: "REGISTER_USER", payload: registeredUser.data });
    };
  
    const authUserCredentials = async (userCredentials) => {
      const userDataFromDb = await authUser(userCredentials);
      localStorage.setItem("access_token", userDataFromDb.token);
      dispatch({
        type: "AUTH_USER",
        payload: userDataFromDb,
      });
    };
  
    const getUserDataByToken = async (token) => {
      const userDataFromDb = await validateUserToken(token);
      dispatch({ type: "LOGGED_GET_DATA", payload: userDataFromDb });
    };
  
    const editUserAccount = async (token, accountData) => {
      const editedUserData = await editAccountData(token, accountData);
      dispatch({ type: "EDIT_USER_ACCOUNT", payload: editedUserData });
    };
  
    const getUserPostsData = async (token) => {
      const postsDataFromDb = await getUserPosts(token);
      dispatch({ type: "FETCH_USER_POSTS", payload: postsDataFromDb });
    };
  
    const getBuddyData = async (nicknameParam) => {
      const userDataFromDb = await accessUserProfile(nicknameParam);
      dispatch({ type: "ACCESS_FRIEND_PAGE", payload: userDataFromDb });
    };
  
    const userLogout = async () => {
      await localStorage.removeItem("access_token");
      const emptyState = {
        ...state,
        userState: {
          userData: "",
          userPosts: "",
        },
      };
      dispatch({ type: "USER_LOGOUT", payload: emptyState });
    };

    return {
      ...state,
      registerSubmitHandler,
      authUserCredentials,
      getUserPostsData,
      userLogout,
      getBuddyData,
      getUserDataByToken,
      editUserAccount,
    };
  }, [state]);

  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );

【讨论】:

  • 我已经编辑了我的问题,但实际上我没有进行任何状态更改,因为我的应用程序中的很多东西都会改变我的状态。
  • 我做不到,但我会尽快尝试,现在,谢谢
  • 另外,即使我已经弄清楚发生了什么,我也会考虑你的小费!再次感谢!
【解决方案2】:

预先感谢您的所有帮助。 我注意到在我使用 Material UI 的某些组件中,它接收到“href”属性,因此,这与我在页面上的导航冲突,所以我删除了“href”链接,应用程序正常工作,但我想通了,因为你们帮助了我! 谢谢大家,这是我的一小段代码:

<Link to="/profile" style={RouterStyledLink}>
  <BottomNavigationAction
    sx={{ color: "#fff", "border-right": "none" }}
    //here was a "href" attribute that refreshed my state!
    label="Home"
    icon={<HomeIcon />}
  />
</Link>

【讨论】:

    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2019-01-05
    相关资源
    最近更新 更多