How to Filter Products in React
Okay, so we've done a lot of preparation now, let's actually get the products in here. So we have the products we want to set them into a product component.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So in order to do this, we have to build a product component and actually display it in here. So let's go into our code and let's see what we have okay. Let's go to shop.js in our components, all right now let's see what we got, we got a shop. Okay, we need a search bar and products, all right let's get the products out of the way first.

So all we have to do is say div and let's say class name is equal to shop__products and then in here we're just simply going to map over our products that we're going to fetch from state or from our mapStateToProps from our store. So let's say products and let's see where is it? Let's go to shop.js in our shopReducer so yeah products, it's going to be setting those products. Now what we want to do is we want to basically return those products and let's map over them now.

Let's say this.props.products.map(product) and then let's just return a div with a class name of shop product and then in here we're just going to say product.title for now and here's what we'll do, shop product description, and shop product title and we'll move this to another component in a second. Okay and we'll say product.title and I we'll say product.description cool.

shop.js

return (
    <div className='shop'>
        {/* shop search bar */}
        <div className='shop__products'>
            {
                this.props.products.map(product => {
                    return (
                        <div className='shop-product'>
                            <div className='shop-product__title'>
                                {product.title}
                            </div>
                            <div className='shop-product__description'>
                                {product.description}
                            </div>
                        </div>
                    )
                })
            }
        </div>
        {/* shop cart button */}
    </div>
)

Cool, now let's go see what happens, we might have to put an if statement in. Okay, it doesn't, all right, so they all have a title and they all have different descriptions right, but they're all different products we are fetching them and setting them and then putting them there okay.

large

So what we need to do is we need to now filter these before we style them and actually dive into this component very much. So when we hit javascript UI we want to filter them obviously. We're already setting the ID or at least we're getting it right, we're printing it into the console, we're not doing anything with it yet. So basically what we want to do is get the key in there and then let's filter them. So let's say div key is equal to product.id, all right, that will get rid of that error.

shop.js

return (
    <div key={product._id} className='shop-product'>
        <div className='shop-product__title'>
            {product.title}
        </div>
        <div className='shop-product__description'>
            {product.description}
        </div>
    </div>
)

Now what I want to do is go into our products shop producer, and let's just get rid of product selected we don't need that. What we want to do is just overwrite products okay, so let's say instead of logging the number let's say content and we'll say products is equal to state.products.map(). And the problem with doing it this way actually is that we need a place to store of all of our products because if we do it this way and we click on a bunch of buttons, eventually is going to contain nothing because we're just going to filter them all out.

So what we need to do is say, we need to do what we were doing. We need to say filteredProducts: [], and then what we can do is we can say filteredProducts is equal to state.products.map

shopReducer.js

const INITIAL_STATE = {
    categories: [],
    products: [],
    filteredProducts: []
}
case FILTER_PRODUCTS_WITH_CATEGORY_ID:
    const filteredProducts = state.products.map
    return {
        ...state,
        //selectedCategoryId
    }
default: return state;

And then we can copy those okay, so if you remember let's go to Google and let's say for each js okay. It says it it doesn't copy okay, but with map it does copy it right. So I want to make that clear because that can be confusing sometimes. Right, so map method creates a new array with the results of calling a provided function on every element in the calling array, so it copies it.

large

Okay, so what we want to do is we want to map over it and we want to say product and then we want to say if product.belongsTo.includes the action.payload which is the id, then we will use it okay, we'll say return product else don't return the product. Then we just need to override it, so let's say filter products.

shopReducer.js

case FILTER_PRODUCTS_WITH_CATEGORY_ID:
    const filteredProducts = state.products.map(product => {
        if(product.belongsTo.includes(action.payload)) {
            return product
        }
    })
    return {
        ...state,
        filteredProducts
    }

And this isn't going to work right away because we're back in shop.js in our component, we're using products. We're not using filterProducts so let's just say filtered products.

shop.js

function mapStateToProps(state) {
    const { categories, filteredProducts } = state.shop;
    return {
        categories,
        filteredProducts
    }
}

Now by default this is still not going to work okay, let's say this.props.products, this is still not going to work immediately once we click on something it will, but you'll see back in our shopReducer, this doesn't contain any products ever, until we do this. So by default it's going to be empty looking, see it's empty.

large

But when we click on something it displays them.

large

It looks like we've got an error, let's see it says id of undefined shop.js:39, let's reload the page and try clicking on one of these, that's not all. Okay, undefined, so let's just check where that error is occurring. We have shop.js:39 so let's go to shop.js:39 and let's make sure it's the right shop.js because we have a couple shop.js's. Okay, you'll see in here shop.js filtered products shop.id. Okay, for some reason it's saying that the product doesn't have an ID and that's probably because our filtered products is empty or something right.

So let's go to our app where it's crashed right, and let's open up the dev tools and see what's going on. Okay, we should have some filtered products and we do, but some of them are null, okay. And that's because we're not returning an array of the same size back in shopReducer it's the same size still. So what we need to do is we need to create a new array and push to that. So we'll say state.products.map and then let's say var filteredProducts is equal to an empty array and then we will just push to that. Okay, so we'll say filteredProducts.push(product) that way it will be of a different size every time, now this will work.

shopReducer.js

case FILTER_PRODUCTS_WITH_CATEGORY_ID:
    var filteredProducts = [];
    state.products.map( product => {
        if(product.belongsTo.includes(action.payload)) {
            filteredProducts.push(product);
        }
    })

Okay javascript, UI/UX, Linux, Python right, it's working great. It's got the full stack development, linux got nothing, UI/UX has user interface and user experience, javascript has full stack and JavaScript, and all has all of them. Okay so the filtering is working properly now, alright and this is a good example of how to use the Chrome dev tools, you can go in here and see where things happen, we saw it was on product id.

Anyway that's working great, what we need to do now is we need to style these okay, we've got them all, we just need to style them and then get the searching working. So maybe we should do the search first, I think that's what we should do first. Basically it's the same thing, it's really simple we'll do it in one video okay.

So let's go ahead and commit our code.

Terminal

git status
git add .
git commit -m "filtered products feature complete"

Now let's go ahead and just check real quick and see if these are working throughout the rest of our app, these buttons, because there's the chance they are not working right, like an account information. So it's working fine, all right, I'll see you in the next video.

Resources

Source code