When you utilize useSelector, the state may be returned as undefined even after it has been initialized

In the process of developing a project that mirrors Twitter(X), my approach involves implementing state management with REDUX and maintaining persistent login using redux-persist. I am storing the user's username and token in both the Redux store (for best practices) and local storage. The project consists of various pages, most notably home and profile. Home displays the user's profile page while Profile renders the PostList. However, I have encountered an issue when using useSelector on the Home and Profile pages. Despite attempts to retrieve the token from the state using useSelector, it consistently returns undefined, which also happens with the username. Although thorough checks through console logging the state and reviewing Redux DevTools indicate that the state is correctly receiving the values, I am unable to retrieve them for unknown reasons.

Despite exploring similar cases on Stack Overflow, none of the solutions provided seem to solve this particular problem.

Below is the code snippet for the Profile page:


'use client'
import { IconButton, Typography, Avatar, Button } from '@mui/material'
import React from 'react'
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Link from 'next/link';
import Image from 'next/image';
import moment from 'moment';
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import ProfileHeaderCategories from '../components/ProfileHeaderCategories';
import { selectAuthToken,selectAuthUser } from '../store/selectors/authSelectors';
import { useSelector } from 'react-redux';

let registrationDate = moment().format('[Joined] MMMM Do YYYY').toString()

const backgroundImageUrl = "/"

const Profile = () => {
    const username = useSelector(selectAuthUser);
    const token = useSelector(selectAuthToken)

    console.log(username, token) // returns undefined

    return (
        <main className='border-r-[0.5px] border-r-gray-600 w-[600px] max-w-[650px]'>
            <div className='flex items-center pl-2 mb-2'>
                <Link href="/home">
                    <IconButton sx={{
                        padding: 1,
                        marginTop: 1,
                    }}
                        className='hover:bg-[#293640] mr-4'
                    >
                        <ArrowBackIcon
                            className='text-white rounded-full text-[20px] font-bold'
                        />

                    </IconButton>
                </Link>
                <Typography variant="h6" className='font-bold'>
                    {username}
                </Typography>
            </div>
            <Image src={backgroundImageUrl} alt="Background Profile pic" width={500} height={500} />
            <div className='flex justify-between'>
                <Avatar sx={{
                    width: 120,
                    height: 120,
                    position: 'absolute',
                    transform: 'translateY(-50%)',
                    marginLeft: 2,
                }}
                    className='border-4 border-[#15202b]' />

            </div>
            <Button className='text-white font-bold bg-[15202b] rounded-full border-gray-600 capitalize float-right'
                sx={{
                    border: 0.5,
                    borderColor: "gray",
                    marginTop: 1,
                    marginRight: 1,
                    padding: 1,
                }}
            >Edit profile</Button>
            <div className='flex flex-col mt-16'>
                <span className='px-4 font-bold text-xl'>{`Your name`}</span>
                <span className='text-gray-400 text-base px-4'>{username}</span>
                <div className='text-base text-gray-400 pt-4 px-4 mb-4'>
                    <CalendarMonthIcon sx={{
                        fontSize: 'medium',
                        marginRight: 1,
                    }} />
                    {registrationDate}
                </div>
            </div>
            <div className='border-b-[0.5px] border-b-slate-500'>
                <ProfileHeaderCategories />
            </div>
        </main>
    )
}


export default Profile

Code for authReducer and store // separate files:

import { createSlice } from '@reduxjs/toolkit';

const authReducer= createSlice({
  name: 'auth',
  initialState: {
    username: null,
    token: null,
    showSignIn: true,
  },
  reducers: {
    setUsername: (state, action) => {
      console.log('Before set name:', state.username);
      state.username = action.payload;
      console.log('After set name:', state.username);
    },
    setToken: (state, action) => {
      console.log('Before setting token:', state.token);
      state.token = action.payload;
      console.log('After setting token:', state.token);
    },
    logout: (state) => {
      state.username = null;
      state.token = null;
      localStorage.clear()
    },
    toggleShowSignIn: (state) => {
      console.log('Before toggle:', state.showSignIn);
      state.showSignIn = !state.showSignIn
      console.log('After toggle:', state.showSignIn);
    }
  }
});
export const { setUsername, setToken, logout, toggleShowSignIn } = authReducer.actions;
export default authReducer.reducer;
'use client'
import { configureStore, combineReducers  } from "@reduxjs/toolkit";
import postSlice from "./slices/postSlice";
import signUpReducer from "./reducers/signUpReducer";
import signInReducer from "./reducers/signInReducer";
import authSlice from "./slices/authSlice";
import storage from 'redux-persist/lib/storage';
import { PersistPartial } from "redux-persist/es/persistReducer";
import {
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist'



// RootState type to include persisted state
export type RootState = ReturnType<typeof rootReducer> & PersistPartial;

const persistConfig = {
  key: 'signData',
  storage,
  whitelist: ['auth'],// only the 'auth' reducer in persisted state
};

// Combine reducers
const rootReducer = combineReducers({
  posts: postSlice,
  signUpForm: signUpReducer,
  signIn: signInReducer,
  auth: authSlice,

});

// Create persisted reducer
const persistedReducer = persistReducer(persistConfig, rootReducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware({
    serializableCheck: {
      ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
    },
})
})

export default store;

Code for selectors:

import { RootState } from "../store";
export interface UsernameAuth {
    username: string
}
export interface TokenAuth {
    token: string
}

export const selectAuthUser = (state: UsernameAuth) => state.username;
export const selectAuthToken = (state: TokenAuth) => state.token;
export const selectShowSignIn = (state: RootState) => state.auth.showSignIn;

Attempting to modify the useSelector function by utilizing a different syntax like: const tokenCheck = useSelector((state) => selectAuthToken(state)) did not yield any results.

Answer №1

To properly select your data, consider implementing the following selectors:

export const selectAuthUser = (state: RootState) => state.auth.username;
export const selectAuthToken = (state: RootState) => state.auth.token;

Similar to how you are handling showSignIn, you can refine it further:

export const selectAuthUser = ({auth}: RootState) => auth.username;
export const selectAuthToken = ({auth}: RootState) => auth.token;

Using useSelector allows you to access the global state stored in Redux.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for invoking an asynchronous cleanup function?

Is it possible to trigger an async cleanup function within useEffect? useEffect(() => { return () => Voice.destroy().then(Voice.removeAllListeners); }, []); Keep in mind that the EffectCallback requires a return of void, not Promise<void> ...

Creating tokens on the server side within next js

At the moment, I am employing next.js' server side rendering to retrieve APIs on the server side. However, I am facing a challenge where these APIs require a token that expires every hour. The complication arises because I am unable to store the token ...

The behavior of an Angular 2 method varies depending on whether it is called in ngOnInit or triggered by a button

In the process of constructing a website with the Angular 2 CLI, I have encountered a perplexing issue. Specifically, I am working on a page that features a reactive form and have developed a method named addQuestion() that is invoked within the ngOnInit l ...

The parameter of type "Construct" cannot be assigned the argument of type "undefined"

I attempted to use code example from the AWS CDK documentation, but it did not function as I had anticipated. Using CDK version 2.62.2 with Typescript. In various parts of the code, a declaration error occurs stating that The argument of type "undefi ...

Accessing node_modules in TypeScript within an Asp.Net Core application

As I work on building a straightforward ASP.NET Core application utilizing npm and TypeScript, the structure of my project is organized as follows: / root | wwwroot | js | AutoGenerated // <-- TS output goes here | view | i ...

Concealing the sidebar in React with the help of Ant Design

I want to create a sidebar that can be hidden by clicking an icon in the navigation bar without using classes. Although I may be approaching this incorrectly, I prefer to keep it simple. The error message I encountered is: (property) collapsed: boolean ...

Employing Multer and Express in conjunction with TypeScript

Overview Currently, I am working on a project that involves creating a user-friendly website where individuals can easily upload images. For this particular task, I have employed Node.js, React, Multer, and Typescript. Issue at Hand app.post('/admi ...

What could be the reason for the gap that shows up when transitioning from one image to the

Check out my website at: This section discusses: https://i.sstatic.net/WTTxJ.gif At the bottom of the image, a 'gap' appears. Instead of using standard HTML img tags, I used Next.js Image like this: <Image src="https://ticket- ...

In React Router, redirect when location.state is not defined

import React, { useState } from "react"; import { Redirect } from "react-router-dom"; function Update(data) { if(!data.location.state) return <Redirect to="/"/> const [name, setName] = useState(dat ...

In need of guidance to troubleshoot the error "Encountering problem while reading properties of undefined (jwt)"

I'm currently facing an authentication flow issue and I am looking for assistance from someone with a keen eye to help me troubleshoot and resolve the problem. The specific error message I am encountering is [next-auth][error][JWT_SESSION_ERROR] http ...

Having trouble with redundant code while updating state in ReactJS - React JS

Currently, I am working on a prayer times web app using reactJS (nextjs). To achieve this, I first fetch the geolocation coordinates and then retrieve the city and country name based on these coordinates. Following that, I obtain the prayer times for the s ...

Create a number line dynamically with Typescript

I am currently working on a project where users can create sales. Within each sale, users are able to add multiple products which are stored in an array and then submitted to a table. I need each product row in the table to have a unique ID known as "line_ ...

It seems that Ionic 2 does not support the registration of custom HTML tags

Encountering a problem with Ionic 2 and custom components. Developed a component to show in a list, serving as the list item. However, my app crashes when attempting to use the custom HTML tag. The stack trace is provided below. Uncertain about the issue. ...

Unable to locate the resource when trying to query DynamoDB

I am having trouble accessing a DynamoDb table, as I keep encountering a "Resource not found" error. The table is set up like this; it's Active and located in the Paris Region (eu-west-3). https://i.sstatic.net/W0IZs.png This is the code snippet I ...

Tips for creating a tailored Express.js request interface using Typescript efficiently

I have been working on designing a custom Express request interface for my API. To achieve this, I created a custom interface named AuthRequest, which extends Request from Express. However, when attempting to import my interface and define req to utilize t ...

What is the best way to link the value of a mat-slider to an input field in a reactive form?

Is there a way to synchronize the min and max values of a ranged mat-slider with corresponding input fields? Currently, when I set numbers in the input fields, the slider updates correctly. However, when I use the slider to change the value of the input fi ...

The Power of Angular Pipes and TypeScript Type Guards

After researching about type guards in TypeScript at this source and this source, I still encountered compiler errors. Error:(21, 14) TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ (callbackfn: (value: Foo, index ...

Implementing Dynamic Updates to a Google Sheets Custom Menu using Typescript

How to Automatically Update a Custom Menu in Google Sheets using Typescript I have successfully set up the following: Dynamically Updating Custom Menu of Google Spreadsheet using Google Apps Script, a demonstration script for dynamically updating the cust ...

Convert coordinates from X and Y within a rotated ImageOverlay to latitude and longitude

After going over all the details in Projection's documentation and conducting various trial and error tests, I have hit a roadblock in finding a solution to this particular issue. All the solutions I have come across assume the x and y coordinates ar ...

What is the best way to retrieve all values stored within a string enum?

Looking to retrieve all values from a string enum. For example, in the following enum, I want to extract ["Red", "Yellow"]: export enum FruitColors { Apple = "Red", Banana = "Yellow", } ...