index
index

Reputation: 3727

react-redux react-router store not available in props

I just started to use redux on my react site. Pretty small. (and I'm following this tutorial https://medium.com/front-end-developers/handcrafting-an-isomorphic-redux-application-with-love-40ada4468af4#.mhkgga84t plugging in some codes to my react site just in case). But when I was in progress and trying to acceess this.props.store it's not available even when I have <Provider store={store}> in my app. Here's my client and app code (I can provide more I just don't know what else to add):

// src/client.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router';

import { routes } from './routes';
import { browserHistory } from 'react-router'

import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import * as reducers from './reducers';
import { fromJS } from 'immutable';

let initialState = window.__INITIAL_STATE__;

Object.keys(initialState).forEach(key => {
  initialState[key] = fromJS(initialState[key]);
});

const reducer = combineReducers(reducers);
const store = createStore(reducer, initialState);
console.log('store', store);

ReactDOM.render(<Provider store={store}><Router routes={routes} history={browserHistory} store={store} /></Provider>, document.getElementById('app'));

but I can't access store from this.props. It should be available here right? So I can do const { todos, dispatch } = this.props; eventually?

// src/components/app.js
import React from 'react';
import { Link } from 'react-router';

import HeaderComponent from './common/header';
import ShareFooterComponent from './common/share-footer';
import FooterComponent from './common/footer';

import { bindActionCreators } from 'redux';
import * as ListingActions from '../actions/listing';
import { connect } from 'react-redux';

export default class AppComponent extends React.Component {
  render() {
    console.log('apps', this.props);
    return (
      <div>
        <HeaderComponent />

        { this.props.children }

        <ShareFooterComponent />
        <FooterComponent />
      </div>
    );
  }
}

Am I missing anything?

Upvotes: 3

Views: 2248

Answers (2)

natac
natac

Reputation: 342

So first thing I noticed that does not seem right is you are passing the store to both the provider and the router

<Provider store={store}><Router routes={routes} history={browserHistory} store={store} /></Provider>

Where it would only be needed in Provider like

<Provider store={store}><Router routes={routes} history={browserHistory} /></Provider>

Then like Ashley Coolman said you will need to connect the component to redux. It can be done with the decorator if your build is set up for it. However you can also import the connect function from react-redux. Documentation on it can be found here.

The way I would hook up your component is the following

class AppComponent extends React.Component {
  render() {
    console.log('apps', this.props);
    return (
      <div>
        <HeaderComponent />
        { this.props.children }
        <ShareFooterComponent />
        <FooterComponent />
      </div>
    );
  }
}

function addTodo(todo) {
    return { type: ADD_TODO, payload: todo }
}

function mapStateToProps(state) {
    // the state is from store.getState()
    // example will pass a todos prop to the connected component
    // so if you want all the state in this component use the spread operator 
    return {
        todos: state.todos
    }
}


function mapDispatchToProps(dispatch) {
    // bindActionCreators will wrap all the function in the passed in object 
    // with the dispatch function so that the actionCreators can be called 
    // directly; without dispatch eg this.props.addTodo(sometodo)
    return bindActionCreators({ addTodo }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(AppComponent )

After that you will have as props on your component both addTodo (function) and todos. Giving you

this.props.todos
this.props.addTodo()

Upvotes: 2

Ashley Coolman
Ashley Coolman

Reputation: 11585

You don't seem to be wiring up your state with the connect decorator. If I am reading the tutorial correctly you should include the line (or something similar based on your state structure):

@connect(state => ({ todos: state.todos }))

or without decorator syntax (more succint version in the comments):

AppComponent = connect(state => ({ todos: state.todos }), null)(AppComponent);
export default AppComponent;`

Upvotes: 3

Related Questions