Uncaught TypeError: Cannot read properties of undefined (reading 'isAuthenticated')

Viewed 256

Im trying to create designated links for users before and after they create an account. Im getting a TypeError but i cannot detect where exactly its coming from. I've tried the chaining method to see if that was where the issue was coming from but that does not seem to be the case.

the error is inserted where i initialize auth as the props im passing into the component.

Heres the code for my navigation links

import { Fragment } from 'react'
import { Link } from "react-router-dom"
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { logout } from '../../actions/auth'

//create links for when users are signed in

const Navbar = ({ auth: {isAuthenticated, loading} , logout}) => {

    const guest = (
        <div className="pr-8 md:block hidden">
                <Link className="p-4 hover:animate-pulse" to='/signup'>Sign up</Link>
                <Link className="p-4 hover:animate-pulse" to='/login'>Login</Link>
            </div>
    )

    const auth = (
        <div className="pr-8 md:block hidden">
                <Link className="p-4 hover:animate-pulse" to='/settings'>Settings</Link>
                <Link onClick={logout} className="p-4 hover:animate-pulse" to='/logout'>Logout</Link>
            </div>
    )

    return (
        <nav className="fixed bg-white shadow-sm h-16  w-full px-5 py-2 flex justify-between items-center font-mono text-lg">
        <Link to ='/login' className="pl-8">Logo</Link>
        <div className="px-4 cursor-pointer md:hidden">
        <svg 
          xmlns="http://www.w3.org/2000/svg" 
          className="h-6 w-6" 
          fill="none" 
          viewBox="0 0 24 24" 
          stroke="currentColor">
    <path 
      strokeLinecap="round" 
      strokeLinejoin="round" 
      strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
        </svg>
         </div>
            <div className="pr-8 md:block hidden">
            { !loading && (
              <Fragment>{ isAuthenticated ? auth : guest }</Fragment>
              ) 
            }
            </div>
        </nav>
    )
}

Navbar.propTypes = {
    logout: PropTypes.func.isRequired,
}

const mapStateToProps = (state) => ({
  auth: state?.auth
})

export default connect(mapStateToProps, { logout })(Navbar) 

Heres my auth reducer where i hold the isAuthenticated in the initialState. I have all my other imports included but they're irrelevant

import { 
    SIGNUP_SUCCESS,
    SIGNUP_FAIL,
    USER_LOADED,
    AUTH_ERROR,
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    LOGOUT,
} from '../actions/types'

const initialState = {
    token: localStorage.getItem('token'),
    isAuthenticated: false,
    loading: true,
    user: null
}

export default function(state = initialState, action ) {

    const { type, payload } = action

    switch(type) {
        case USER_LOADED: 
            return {
            ...state,
            isAuthenticated: true,
            loading: false,
            user: payload
        }

        case SIGNUP_SUCCESS:
        case LOGIN_SUCCESS:
            localStorage.getItem('token', payload.token)
            return {
                ...state,
                ...payload,
                isAuthenticated: true,
                loading: false,
            }

        case LOGIN_FAIL:
        case SIGNUP_FAIL:
        case AUTH_ERROR:
        case LOGOUT:
            localStorage.removeItem('token')
            return {
                ...state,
                token: null,
                isAuthenticated: false,
                loading: false
            }
    
            default: 
            return state
    }
}

heres my store configuration

import reducerData from '../reducers/auth'
import {applyMiddleware, createStore} from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension'
import thunk from 'redux-thunk'


const initialState = {}

const middleware = [thunk]

const store = createStore(reducerData, initialState, composeWithDevTools(applyMiddleware(...middleware)))

export default store
1 Answers

Where is your store configuration ? i.e. wherever you are creating your redux store you will have a root reducer ( if you have multiple reducers usually you would ) and the name you give there that will be your redux state object's property name by which you can access it in your components when you connect your component. i.e if you're using redux toolkit then you would use like this . Whatever name you will be referring here for your authorization reducer will come down as the prop name when you do mapStateToProps.

I think the problem is you are giving it a different name in your store configuration and you are trying to access the object using a different name in your component

and that's why it is throwing the error

make sure you are using the same name in your component as what you are using it in your redux state object

Related