Search code examples
reactjsreact-routerreact-reduxjsxreact-router-redux

How to send props to sub routed-component with React-Router and React-Redux?


I'm creating website with React + React-Router and React-redux. This is my store and reducer:

const defaultState = {
    posts: [{key:0, title: 'Default post', text: 'Every visitor is welcome!'}]
};

const store = createStore(
    (state = defaultState, action) => {
        switch(action.type) {
            default:
                return state;
        }
    }
);

i don't have any action yet, i will add it later. however, back to the point, this is App Component which is entry point of React App.

const App = React.createClass({
    render() {

        return (
            <div>
                <h1>React Router + Redux Blog</h1>

                <ul>
                    <li><IndexLink to="/">Main</IndexLink></li>
                    <li><Link to="/about">About</Link></li>
                    <li><Link to="/posts">Posts</Link></li>
                </ul>

                {this.props.children}
            </div>
        );
    }
});

and this App component will connect with Redux-Router's connect method:

const ConnectedApp = connect( (state) => {
    return {
        posts: state.posts
    };
})(App);

now, the last, i will give Router component instead of ConnectedApp inside of Provider, and use ConnectedApp as index component.

ReactDOM.render(
    <Provider store={store}>
        <Router history={browserHistory}>
            <Route path="/" component={ConnectedApp}>
                <IndexRoute component={Main} />
                <Route path="about" component={About} />
                <Route path="posts" component={Posts} >
                    <IndexRoute component={PostsMain} posts={[]} />
                    <Route path="write" component={PostsWrite} />
                </Route>
            </Route>
        </Router>
    </Provider>,
    document.getElementById('app')
);

now, this is the problem. i want to send Redux Store states into sub component(PostsMain or PostsWrite) as Props, but i don't know how to pass it. every sub component might be rendered is decided by React Router, and each component doesn't have any stored state by Redux.

I saw some modules like React-Router-Redux, Redux-Router, but I want to do it without them. If someone knows how to do it, please gimme advice and that will be very appreciated.


Solution

  • If you want some components in your tree to receive Redux's state data, you have to make them "container components" by using React-Redux library’s connect() function.

    For example, you could write a "PostsMain" container like this:

    import { connect } from 'react-redux';
    import PostsMainComponent from '../components/posts_main_component.jsx';
    
    const mapStateToProps = (state) => {
        return {
            // the desired props calculated from the store's state, for example:
            posts: state.posts,
        };
    };
    
    const PostsMainContainer = connect(
        mapStateToProps,
    )(PostsMainComponent);
    
    export default PostsMainContainer;
    

    Then use it in your routes declaration like this:

    <IndexRoute component={PostsMainContainer} />
    

    You'll find detailed information about container components in Redux's doc and this post by Dan Abramov.