In order to filter our todos, let's create a selector function. I'll add this just above the reducer function in todo.js. I'll start by exporting a new constant which I'm going to call getVisibleTodos, and getVisibleTodos is going to be a function that's going to accept two arguments.
It's going to accept a list of todos, and it's going to accept a string that we'll use to filter on. Just like our reducer, we're going to use a switch statement here to alter our return value based on the passed-in filter.
I'm going to switch on filter, and I'm going to add a default case where I'm just going to return the todos that have been passed in. I'm also going to add a case for active where I'm going to return the existing todos.filter, and I'm going to return that if my todo is not complete.
I'm going to add a second case, this will be for completed, and here I'm going to do the opposite where I'm going to return todos.filter and I'll return all the todos where they are complete.
With that done, I'm going to save this file, and let's open up app.js and figure out how we can get this filtered value from our links into our component. Up at the top of the file, we're importing BrowserRouter as Router. I'm also going to import the route component from react-router.
I'm going to come back down into my render method, and I'm going to add a route, and I'm going to give that route a path prop. That path is going to be /:filter, and this is going to create a parameter on this route called filter. I'm going to make that optional with the question mark, and then I'm going to use route's render prop.
Render is going to take a function that'll render in response to route. This function is going to receive some arguments, and I'm going to destructure those and just grab match from the arguments that are passed into render.
I'm going to use some parentheses her so I can return some JSX, and in this case, it's going to be my todoList component, and I just want to close out that route tag. Now, in todoList I want to use this match to pass in a new property to todoList I'm going to call filter.
Filter's going to be equivalent to match.params.filter, which is going to be the value in our path. When we look at our links here, I'll have /active, so my filter name will be active when I click on this link, or my filter name will be completed when I click on the completed link, and that will get passed into todoList as a filter value.
I can save this, now all we have left is to wire this all up to our todoList component so we can filter our todos. I'm going to open todoList.js, and I'm going to update my import from my reducer file, and I'm also going to import our getVisibleTodos selector function.
Now I'm going to scroll down to the bottom where we're calling connect, and I want to update my mapStateToProps function to use getVisibleTodos to decide which todos to pass in as props.
In order to do this, we need our two arguments. Our first argument is a list of todos, which is going to be our existingState.Todo.TodosValue, but we also need to get our filter. When we added our todoList to our route in app.js, we're passing filter in as a property of the todoList component, which we don't directly have access to at this point.
MapStateToProps gives us a second argument which is called ownProps, and this is going to give us the props that have been attached directly to the instance of our component and that means we can come in here and we can reference ownProps.filter and pass the filter that our router gave us into our selector function and get back our filtered todos.
If I save this, and I go into the browser and I click active, we're only going to see active todos, and if I click completed, we're only going to see completed todos, and all should give us our entire list.