Long Phan Long Phan - 1 month ago 13
React JSX Question

New to react and Redux, why am i getting an undefined store being passed?

I am not sure if I am even setting up this redux-react project correctly. I am confused as to how I can actually start using store within my react app.

When I try to console.log store I am getting undefined. I have gotten most of this from a boilerplate and am unsure of how some of these parts interact. Currently I have an index.js with

import { Provider } from 'react-redux'
import { configureStore } from './store/configureStore';
const store = configureStore()


import { Root} from './containers/Root';
import Home from './containers/Home'
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={Root}>
<IndexRoute component={Home} />
</Route>
</Router>
</Provider>,
document.getElementById('root')
);


Root.js :

import React, { Component } from 'react';
import DevTools from './DevTools';
import MyNavbar from '../components/MyNavbar';
import Footer from '../components/Footer'

module.exports = class Root extends Component {
render() {
const { store } = this.props;

console.log(store)

return (
<div>
<MyNavbar />
{this.props.children}
<Footer />
{/* Being the dev version of our Root component, we include DevTools below */}
{/*<DevTools />*/}
</div>


);
}
};


Home component:

import React, { Component, PropTypes } from 'react';
import { Row, Col, Grid } from 'react-bootstrap'
import HowItWorks from '../components/HowItWorks'
import GetStarted from '../components/GetStarted'
import Setup from './Setup'




export default class Home extends Component {
render() {
// we can use ES6's object destructuring to effectively 'unpack' our props
return (
<section>
<div className="slider-wrapper">
<GetStarted />
</div>
<Grid>
<div className="howwork-wrapper">
<Row >
<Col md={12}>
<HowItWorks />
</Col>
</Row>
</div>
</Grid>
</section>

);
}
}


configureStore.js :

import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from '../reducers';
import createLogger from 'redux-logger';
import thunk from 'redux-thunk';
import DevTools from '../containers/DevTools';


const logger = createLogger();

const finalCreateStore = compose(
applyMiddleware(logger, thunk),
DevTools.instrument()
)(createStore);

module.exports = function configureStore(initialState) {
const store = finalCreateStore(rootReducer, initialState);
if (module.hot) {
module.hot.accept('../reducers', () =>
store.replaceReducer(require('../reducers'))
);
}

return store;
};


reducers/index.js:

import { combineReducers } from 'redux';

import auth from './auth'


const rootReducer = combineReducers({
auth
});

export default rootReducer;


reducers/auth.js:

import { LOGIN, LOGIN_FAIL, LOGOUT } from '../constants/ActionTypes'
export default function auth(state = {}, action) {
switch (action.type) {
case LOGIN:
return state;
case LOGIN_FAIL:
return state ;
case LOGOUT:
return state ;
default:
return state;
}
}


constants/ActionTypes:

export const LOGIN = 'LOGIN';
export const LOGIN_FAIL = 'LOGIN_FAIL';
export const LOGOUT = 'LOGOUT';

Answer

You need to connect your components to get access to the store/state. To do this, modify your Root component like this:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import DevTools from './DevTools';
import MyNavbar from '../components/MyNavbar';
import Footer from '../components/Footer'

class Root extends Component {
  render() {
    const { state } = this.props;

    console.log(state)

    return (
          <div>
            <MyNavbar />
            {this.props.children}
            <Footer />
            {/* Being the dev version of our Root component, we include DevTools below */}
            {/*<DevTools />*/}
          </div>


    );
  }
};

const mapStateToProps = (state) => {
  return {
    state: state
  }
}

module.exports = connect(mapStateToProps)(Root);

A few notes, since you are transpiling anyway, you could export instead of module.exports in your declaration. Also, generally you do not want to expose your entire state to a single component. You can connect multiple components (make them "containers") by following this pattern.

The following is an example component connected to your state.

import React, { Component } from 'react';
import { connect } from 'react-redux';

export class SomeComponent extends Component {
  render() {
    const { someKey, dispatchSomething } = this.props;

    return (
      <div onClick={dispatchSomething}>
        <h1>My rendered someKey variable: {someKey}</h1>
      </div>
    );
  }
};

const mapStateToProps = (state) => {
  return {
    someKey: state.someReducer.someKey
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    dispatchSomething: () => dispatch(someActionCreator())
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(SomeComponent);

References