N.K.
N.K.

Reputation: 65

React Redux prop is undefined

Beginner question. I want to pass a user object to a component from store as a prop, but the component doesn't get it (undefined). I get the user object from a third party service authentication service (google firebase)

The middleware actually logs out in the console that the action of type SET_CURRENT_USER takes place, and next state indeed will have a user.currentUser set to the object returned from the login service (NOT UNDEFINED).

However, the component doesn't re-render and doesn't seem to receive the object as prop

The component, in which the prop is undefined

import React from 'react';
import { connect } from 'react-redux';
import { auth } from "../../firebase/firebase.utils";

export const Navbar = ({ currentUser }) => {
    return (
        /* A LOT OF JSX CODE. currentUser IS UNDEFINED */
    );
};

const mapStateToProps = state => ({
    currentUser: state.user.currentUser
});

export default connect(mapStateToProps)(Navbar);

The App component, which has the above component as a child. Also, I'm trying to set the store to contain the user object in the componentDidMount()

import React from 'react';
import Homepage from "./pages/homepage";
import { Route, Switch } from 'react-router-dom';
import { connect } from 'react-redux';

import Login from "./pages/login";
import Register from "./pages/register";
import { Navbar } from "./components/navbar/navbar";

import { auth } from "./firebase/firebase.utils";
import { setCurrentUser } from "./redux/user/user.actions";

class App extends React.Component {
    unsubscribeFromAuth = null;

    componentDidMount() {
        this.unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
            if(userAuth) {
                (async () => {
                    const rawResponse = await fetch(/* JUST AN ASYNC FUNCTION TO POST TO BACKEND*/);
                })();
            }
            this.props.setCurrentUser(userAuth); /*HERE IM TRYING TO SET THE STORE*/
        })
    }

    componentWillUnmount() {
        this.unsubscribeFromAuth();
    }

    render() {
        return (
            <div>
                <Navbar /> /* THE COMPONENT WHICH SHOULD GET THE USER OBJECT AS PROP */
                <Switch>
                    <Route exact={true} path={'/register'} component={Register} />
                    <Route exact={true} path={'/login'} component={Login} />
                    <Route path={'/'} component={Homepage} />
                </Switch>
            </div>
        );
    }
}

const mapDispatchToProps = (dispatch) => ({
    setCurrentUser: user => dispatch(setCurrentUser(user))
});

export default connect(null, mapDispatchToProps)(App);

The index component

import React from 'react';
import ReactDOM from 'react-dom';
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import { Provider } from 'react-redux';

import store from "./redux/store";

ReactDOM.render(
    <Provider store={store} > /* HERE IS STORE PROVIDED FROM IMPORT*/
        <BrowserRouter>
            <App/>
        </BrowserRouter>
    </Provider>,
    document.getElementById('root')
);

Root reducer

import { combineReducers } from "redux";

export default combineReducers({
    user: userReducer
});

User reducer

const INITIAL_STATE = {
    currentUser: null
};

const userReducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case 'SET_CURRENT_USER':
            return {
                ...state,
                currentUser: action.payload
            };
        default:
            return state;
    }
};

export default userReducer;

User action

export const setCurrentUser = user => ({
    type: 'SET_CURRENT_USER',
    payload: user
});

The store

import { createStore, applyMiddleware } from "redux";
import logger from 'redux-logger';

import rootReducer from './root-reducer';

const middlewares = [logger];

const store = createStore(rootReducer, applyMiddleware(...middlewares));

export default store;

Upvotes: 2

Views: 729

Answers (1)

Brian Thompson
Brian Thompson

Reputation: 14355

You're doing both a named and default export for Navbar. The default export gets wrapped by the connect HOC that adds currentUser to its props. The named export does not.

You import it named like this: import { Navbar } from. Instead use the default export: import Navbar from.

Then I would suggest removing the named export to avoid future confusion.

Upvotes: 3

Related Questions