08. Using withRouter() to Inject the Params into Connected Components

Video Link

Currently we are reading params.filter passed by the Router inside of the App component. We can access the params from there because the router injects the params prop into any Route handler component specified in the route configuration. In this case, the filter is passed inside params.

However, the App component itself doesn't use filter, it just passes it to VisibleTodoList, which uses it to calculate the currently visible Todos.

Passing the params from the top level of Route Handlers gets tedious, so we'll remove the filter prop. Instead, we'll find a way to read the current Router params in the VisibleTodoList itself.

App.js Before:

const App = ({ params }) => (
  <div>
    <AddTodo />
    <VisibleTodoList
      filter={params.filter || 'all'}
    />
    <Footer />
  </div>
);

App.js After:

const App = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
);

Updating VisibleTodoList

We will start by importing withRouter from React Router (version 3+):

import { withRouter } from 'react-router'

withRouter takes a React component and returns a different React component that injects the router-related props such as params into your component.

We want params to be available inside of mapStateToProps, so we need to wrap the connect() result so that the connected component gets the params as a prop.

We will also need to change mapStateToProps to read the filter from ownProps.params instead of ownProps directly.

Like before, we'll specify the fallback value to 'all'.

VisibleTodoList Before:

const mapStateToProps = (state, ownProps) => ({
  todos: getVisibleTodos(
    state.todos,
    ownProps.filter
  ),
});

// mapDispatchToProps ...

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

VisibleTodoList After:

const mapStateToProps = (state, ownProps) => ({
  todos: getVisibleTodos(
    state.todos,
    ownProps.params.filter || 'all'),
});

// mapDispatchToProps ...

const VisibleTodoList = withRouter(connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList));

We can make mapStateToProps even more compact by reading params directly from the argument definition thanks to the ES6 destructuring syntax:

const mapStateToProps = (state, { params }) => ({
  todos: getVisibleTodos(state.todos, params.filter || 'all'),
});

Recap at 1:51 in video

results matching ""

    No results matching ""