3

I am trying to intergrate redux-auth-wrapper into the react boilerplate.

According to my debugging tools, the browser has the state set correctly (user: {data: null, isLoading: false}), however the App is saying that state is undefined.

mapStateToProps does seem to be given the state correctly?

Reducer:

containers/App/reducer.js:

import { fromJS } from 'immutable';

import {
    USER_LOGGING_IN,
  USER_LOGGED_IN,
  USER_LOGGED_OUT,
} from '../../constants';

const userInitialState = fromJS({
    data: null,
    isLoading: false,
});

function userReducer(state = userInitialState, action) {
    switch (action.type) {
        case USER_LOGGING_IN:
            return state
                .set('isLoading', true);
        case USER_LOGGED_IN:
            return state
                .set('data', action.payload)
                .set('isLoading', false);
        case USER_LOGGED_OUT:
            return userInitialState;
        default:
            return state;
    }
}

export default userReducer;

containers/App/index.js

import React from 'react';
import { Route, NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout } from '../../actions/user';

import Home from '../../components/Home';

const getUserName = (user) => {
  if (user.data) {
    return `Welcome ${user.data.name}`;
  }
  return ('Not logged in');
};


const UserName = ({ user }) => (<div>{getUserName(user)}</div>)

function App({ user, logout }) {
  return (
    <div>
      <h1>Test App</h1>
      <div>
        <nav>
          <NavLink exact to="/">Home</NavLink>
        </nav>
        <nav>
        </nav>
        <div>
          <Route exact path="/" component={Home} />
        </div>
      </div>
    </div>
  );
}

const mapStateToProps = (state) => ({
  user: state.user, -- this is undefined when it should not be
});

export default connect(mapStateToProps, { logout })(App);

reducers.js:

/**
 * Combine all reducers in this file and export the combined reducers.
 */

import { fromJS } from 'immutable';
import { combineReducers } from 'redux-immutable';
import { LOCATION_CHANGE } from 'react-router-redux';

import languageProviderReducer from 'containers/LanguageProvider/reducer';
import userReducer from 'containers/App/reducer';

/*
 * routeReducer
 *
 * The reducer merges route location changes into our immutable state.
 * The change is necessitated by moving to react-router-redux@5
 *
 */

// Initial routing state
const routeInitialState = fromJS({
  location: null,
});

/**
 * Merge route into the global application state
 */
function routeReducer(state = routeInitialState, action) {
  switch (action.type) {
    /* istanbul ignore next */
    case LOCATION_CHANGE:
      return state.merge({
        location: action.payload,
      });
    default:
      return state;
  }
}

/**
 * Creates the main reducer with the dynamically injected ones
 */
export default function createReducer(injectedReducers) {
  return combineReducers({
    route: routeReducer,
    language: languageProviderReducer,
      user: userReducer,
    ...injectedReducers,
  });
}

This is just the react boilerplate, but mixed with the react router 4 example (auth.js, constants.js, App/reducer.js, App/index.js etc)

2 Answers 2

2

State is an immutable object. For you to use it as an simple javacsript object, use .toJS().

const mapStateToProps = (immutableState) => {
  const state = immutableState.toJS();
  return {
    user: state.user,
    --this should work correctly now
  };
};

Let me know if this solves.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I implemented this slightly differently (using selectors), but not using .toJS() was the problem!
No problem sir ☺
0
const userInitialState = fromJS({
    data: null,
    isLoading: false,
});

would this not return state.data and state.isLoading?

const mapStateToProps = (state) => ({
  user: state.user, -- this is undefined when it should not be
});

I don't see anywhere that you've declared 'user' as a key on your state object.

1 Comment

No, it is only setting the original state of the userReducer to {data: null, isLoading: false}. The key I am using is being set by the createReducers function (user: userReducer). My debugging tools show the state generated correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.