skip to Main Content

I’ve looked up for hours and I just can’t find any solution for my problem.

I’m developing an app that uses react context and I’m also using react-router-dom to navigate through my pages.

This context file, has a initial state, for I am using useReducer hook to change it.
But when I navigate along application, like changing or switch pages my state realoads and I can’t get data from my state unless I make a new get request.

I’ve read somewhere that react-router-dom is refreshing my pages so I can’t make it.

Is there any tip you guys can give me?

Actually I can’t think about a solution since I am confusing about how do I make the state "permanent"

there is my index:

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")
);

Here is my context:

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 };

2

Answers


  1. Chosen as BEST ANSWER

    in advance, I would like to thank you for all your help. I've noticed that in some components that I use material UI, it receives the "href" property, so, this was conflicting with my navigation along the pages, so I've removed the "href" links, and the application works properly, but I figured out things because you guys helped me! Thank you all, here's a little piece of my code:

    <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>
    

  2. I don’t see anything very odd with your code.

    Nevertheless, it is a best practise to encapsulate your context value in a memo. If you don’t do that, all components which consume this context render more times than they need.

    Could you try that please?

    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>
      );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search