Search code examples
cookiesreact-hookslocal-storagenext.js13

Can't update react state in context hook


Lately I have been working on a next.js project using latest next 13.8. But while using the context hook I got into a trouble.

Context

"use client";
// REACT ESSENTIALS
import React, { useState, useContext } from "react";
// IMPORTING CONTEXT
import AuthContext from "./context";

// OTHER IMPORTS
import Cookies from "js-cookie";
import { v4 } from "uuid";

export const AuthState = (props) => {
  // VARIABLE SETTINGS
  const host = process.env.NEXT_PUBLIC_BACKENED_API_URI;
  const [user, setUser] = useState(null);

  // FUNCTION TO SAVE DATA TO BOTH LOCALSTORAGE & COOKIE
  const createCookiesToLocalStorage = (name, val) => {
    Cookies.set(name, val);
    localStorage.setItem(name, val);
  };

  // INITIATING USER TO GET JWT
  const initiateUser = async (credentials) => {
    const { identifier, password } = credentials;
    const req = await fetch(host + "/api/auth/local", {
      method: "POST",
      mode: "cors",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ identifier, password }),
    });

    const response = await req.json();

    if (response.jwt) {
      setUser(response.user);

      createCookiesToLocalStorage("jwt", response.jwt);
      createCookiesToLocalStorage("user", JSON.stringify(response.user));
    }
    return response;
  };

  // GETTING USER AGAIN WITH THE JWT
  const getSetUser = async (jwt) => {
    const extUsr = Cookies.get("user") || localStorage.getItem("user");
    if (extUsr) {
      console.log(extUsr);
      setUser(extUsr);
    } else {
      const req = await fetch(
        host + "/api/users/me?populate=*&populate=profile.image",
        {
          method: "GET",
          mode: "cors",
          headers: {
            "Content-Type": "application/json",
            "Access-Control-Allow-Headers":
              "Accept, Authorization, Content-Type",
            Accept: "*/*",
            Authorization: `Bearer ${jwt}`,
          },
        }
      );
      const response = await req.json();
      setUser(response);
    }
  };

  // Other stuffs 

  return (
    <AuthContext.Provider
      value={{
        user,
        setUser,
        initiateUser,
      }}
    >
      {props.children}
    </AuthContext.Provider>
  );
};

export const useAuthContext = () => useContext(AuthContext);

So whenever I run initiateUser() command it stores the "user" object as a json array to localStorage (also in cookies using js-cookie). But whenever I try to assign that json arrray to the user state it is returning null.

Simply the setUser() command is not assigning the "user" array fetched from localStorgae. The console.log(extUsr) ouput isn't null, rather it is returnibg the user array.

I want somebody to help me out with how to set that fetched details to that react state.


Solution

  • Actually after browsing through my code deeply I got to know I was saving the code as string format not as an object. That's why I was getting weird type of responses.

    So I did the following changes

     // INITIATING USER TO GET JWT
      const initiateUser = async (credentials) => {
        const { identifier, password } = credentials;
        const req = await fetch(host + "/api/auth/local", {
          method: "POST",
          mode: "cors",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ identifier, password }),
        });
    
        const response = await req.json();
    
        if (response.jwt) {
          setUser(response.user);
    
          createCookiesToLocalStorage("jwt", response.jwt);
          createCookiesToLocalStorage("user", JSON.stringify(response.user));
        }
        return response;
      };
    
      // UPDATE USER WITH JWT
      const fetchToSetUser = async (jwt) => {
        const req = await fetch(
          host + "/api/users/me?populate=*&populate=profile.image",
          {
            method: "GET",
            mode: "cors",
            headers: {
              "Content-Type": "application/json",
              "Access-Control-Allow-Headers": "Accept, Authorization, Content-Type",
              Accept: "*/*",
              Authorization: `Bearer ${jwt}`,
            },
          }
        );
        const response = await req.json();
        setUser(response);
      };
    
      // GETTING USER AGAIN WITH THE JWT
      const getSetUser = async (jwt, _usr) => {
        if (_usr) {
          setUser(JSON.parse(_usr));
        } else {
          await fetchToSetUser(jwt);
        }
      };