1. 25
    Filter State Data in Redux with a Selector Function and React Router
    4m 22s

Filter State Data in Redux with a Selector Function and React Router

Andy Van Slaars
InstructorAndy Van Slaars

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 3 years ago

In this lesson, we’ll wire up React Router to pass a url based filter parameter into our component and create a selector function to filter our state data between the store and our components by hooking into the ownProps parameter of mapStateToProps.

[00:00] 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.

[00:18] 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.

[00:33] 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.

[01:02] 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.

[01:20] 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.

[01:36] 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.

[01:58] 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.

[02:11] 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.

[02:30] 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.

[02:53] 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.

[03:09] 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.

[03:25] 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.

[03:46] 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.

[04:08] 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.

Erick Lee
Erick Lee
~ 5 years ago

Great course Andrew,

I am having a problem on this lesson where the application is not recognizing whether task is active or completed. I have validated that checking a box changes the todo in the json-server DB and have made the change from defaultChecked to checked on the checkbox input. However /active shows both items with checkboxes and those without, while completed does not show anything. The strange thing is that in the browser ALL of the list items show the same value for the checkbox <input type="checkbox" value="on">.

Erick Lee
Erick Lee
~ 5 years ago

I found my error. Thanks again for a great course.

Andy Van Slaars
Andy Van Slaarsinstructor
~ 5 years ago

I found my error. Thanks again for a great course.

Sorry I didn't see your original question earlier. Glad you were able to find a solution!

Paul
Paul
~ 5 years ago

Hey Andrew,

Having nearly completed this excellent, course, I've stumbled on an issue attempting to view all tasks. It appears that accessing http://localhost:3000/ ends up with a stripped trailing slack http://localhost:3000, and thus the path='/:filter' fails. If I change the <Link to='all'> then it works okay.

Any pointers? Cheers

Andy Van Slaars
Andy Van Slaarsinstructor
~ 5 years ago

Paul,

Thanks, glad you've enjoyed the course so far. This might be because you are missing the ? on the filter parameter. It's a small difference and easy to miss, but this way, even when filter is undefined it will match the route, and render the component. Without that ?, it won't match the route, and the todo list component isn't rendered.

https://github.com/avanslaars/egghead_react_redux_course/blob/25-filter-todos/src/App.js#L22

Hope this clears it up for you!

Paul
Paul
~ 5 years ago

Cheers, that worked a treat!