07. Filtering Redux State with React Router Params
Now we're using the Link
s provided by React Router, so when we click a link the URL gets updated. However, the content doesn't get updated because the visible TodoList
component in its mapStateToProps
function still depends on the visibilityFilter
in the Redux store instead of reading it from the URL.
mapStateToProps
Before:
const mapStateToProps = (state) => ({
todos: getVisibleTodos(
state.todos,
state.visibilityFilter
)
})
In order to fix this, we'll add an argument ownProps
, and we'll read the visibilityFilter
from ownProps
.
mapStateToProps
After:
const mapStateToProps = (state, ownProps) => ({
todos: getVisibleTodos(
state.todos,
ownProps.filter
)
})
We will also update our getVisibleTodos
function to use our current convention for filter props 'all'
, 'completed'
, and 'after'
.
getVisibleTodos
Before:
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed);
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed);
default:
throw new Error(`Unknown filter: ${filter}.`);
}
};
getVisibleTodos
After:
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'all':
return todos;
case 'completed':
return todos.filter(t => t.completed);
case 'active':
return todos.filter(t => !t.completed);
default:
throw new Error(`Unknown filter: ${filter}.`);
}
};
Updating App.js
Since the VisibleTodoList
component gets rendered from the app, we need to add the filter
prop to make it available in the mapStateToProps
function of the VisibleTodoList
.
We want the filter prop to correspond to the current filter
parameter in our route configuration (the path='/(:filter)'
we set in a previous lesson). React Router makes these parameters available to the route handler componens in a special prop called params
, so we will add params
as a prop to App
. Now we will be able to read the filter from params.filter
.
Since the filter
param is empty on the root path, we'll pass 'all'
to VisibleTodoList
as a fallback.
const App = ({ params }) => (
<div>
<AddTodo />
<VisibleTodoList
filter={params.filter || 'all'}
/>
<Footer />
</div>
);
Now that our visbility filters are managed by React Router, we no longer need the visibilityFilter
reducer. We can delete it, and also remove it from the combineReducers()
declaration in index.js
.