Search code examples
reactjsreduxreact-redux

Cannot fetch redux state from component


I am trying to fetch the redux state (user auth state). I tried to console.log it in the mapStateProps variable but all i get is undefined. I tried doing the same from the reducer and I get the variable properly after I initialize it, but when i pass it to the AuthReducer method I do not get an output at all, or see the state variables in the chrome redux dev-tool.

it seems as if the main function AuthReducer doesnt "see" the state variable.

Console:

AuthReducer.js:41 {isLoggedIn: false, accessToken: 'lalaa', username: '', email: '', exp: ''} (<==== right after initialization and before AuthReducer method)
App.js:50 {AuthReducer: ƒ, RegisterReducer: ƒ} 
App.js:51 undefined

AuthReducer.js:

import AuthTypes from "./AuthTypes"
// import axios from 'axios'

const authState = {
// const authState = {
    isLoggedIn: false, 
    accessToken: "lalaa", 
    username: "", 
    email: "", 
    exp: "", 
    // authorities: ["USER"]
}

// function getAuthState (state = authState) {
//     let token = sessionStorage.getItem('token')
//     let expiration = parseInt(sessionStorage.getItem('exp')) // originaly a string 
//     let loggedIn = sessionStorage.getItem('isLoggedIn')
//     try {       
//         if ( (new Date(expiration)) > new Date() ) {
//             console.log('not expired')
//             axios.defaults.headers.common["Authorization"] = `Bearer ${token}`
//             return {
//                 ...state, 
//                 accessToken: token,
//                 exp: expiration,
//                 isLoggedIn: loggedIn,
//             }
//         }
//         // console.log('in try')
//         return state
//     }
//     catch (error) {
//         console.log('in catch')
//         console.log('there was an error: ' + error)
//         return state
//     }
// }

// authState = getAuthState()
// const newAuthState = getAuthState()
console.log(authState)

const AuthReducer = (state = authState, action) => {
// const AuthReducer = (state = newAuthState, action) => {
    console.log('in reducer method')
    console.log(state)
    
    switch (action.type) {

        case AuthTypes.LOGIN_SUCCESS: {
            return {
                ...state,
                isLoggedIn: action.payload.isLoggedIn,
                accessToken: action.payload.accessToken,
                exp: action.payload.exp,
                // username: action.payload.username,
                // email: action.payload.email,
            }
        }

        case AuthTypes.LOGIN_FAIL: 
            return {
                ...state,
                isLoggedIn: false,
                accessToken: '',
                exp: 0,
                // username: action.payload.username,
                // email: action.payload.email,
            }

        default: return state
    }
}

export default AuthReducer

App.js:

// import {Redirect} from 'react-router-dom'
import './App.css'

import { BrowserRouter, Route, Switch } from 'react-router-dom' // Changed "BrowserRouter" in faivor of "Rotuer"
import { connect } from 'react-redux'
import axios from 'axios'
import { AuthActions } from './redux/Auth/AuthActions'


import Login from './pages/Login/Login'
import Register from './pages/Register/Register'

import Header from './components/Layout/Header/Header'
import Footer from './components/Layout/Footer/Footer'

// import store from './redux/store'
axios.defaults.baseURL=process.env.REACT_APP_API_URL // Set a default url for axios


const App = (props) => {

    return (
        <div className="App">
            <BrowserRouter>
                <Switch>
                    
                    <Route path='/test'>
                        <Header/>
                            Main
                        <Footer/>
                    </Route>

                    <Route exact path="/login"> 
                        <Login />
                    </Route>
                    
                    <Route exact path="/register">
                        <Register />
                    </Route> 
                
                </Switch>
            </BrowserRouter>

        
        </div>
    )
}

const mapStateToProps = (state) => {
    console.log(state)
    console.log(state.isLoggedIn)
    return {
        isLoggedIn: state.isLoggedIn,
    }
}

// const mapDispatchToProps = dispatch => {
//  return {
//      // authorized: true
//      authorized: () => {
//          dispatch(AuthActions())
//      }
//  }
// }

export default connect(
    mapStateToProps, 
    // mapDispatchToProps
)(App)

store.js:

import { createStore, compose, applyMiddleware } from 'redux'
// import { createStore} from 'redux'
import AuthReducer from './Auth/AuthReducer'
import RegisterReducer from './Register/RegisterReducer'
import thunk from 'redux-thunk'


const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose
// const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const reducers = () => {
    return {
        AuthReducer, 
        RegisterReducer, 
        
    }
}

const store = createStore(
    reducers, 
    composeEnhancers(applyMiddleware(thunk)),
)

export default store

A little bit of what I eventually want to accomplish (just to make sure the answers here are relevant..): I want to check if a user is logged in so I know there to redirect when running the app. (if logged in and access the /login page, so the user is redirected to the /test page. and the opposite). In AuthReducer.js there is a commented out function that basically fetches data from the local session and applies it to the webapp state.


Solution

  • I think you're not accesing correctly the reducer in the mapStateToProps and I will do this in your setup of the store to create the store state:

    import { createStore, combineReducers, compose, applyMiddleware } from 'redux'
    import AuthReducer from './Auth/AuthReducer'
    import RegisterReducer from './Register/RegisterReducer'
    import thunk from 'redux-thunk'
    
    const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose
    
    // Combine the reducers using the combineReducers function to make it a big object containing the auth and register keys in this example.
    const reducers = combineReducers({
        auth: AuthReducer, 
        register: RegisterReducer, 
    });
    
    
    const store = createStore(
        reducers, 
        composeEnhancers(applyMiddleware(thunk)),
    )
    
    export default store
    

    Now in your mapStateToProps function you need to call it like this:

    const mapStateToProps = (state) => ({
            // Look how it references the auth key I just made in the combineReducers function.
            isLoggedIn: state.auth.isLoggedIn,
    });