0

Main issue: Two components are connected to the Redux store. One component re-renders while the other does not when the state changes.

I am using react-redux. I have a parent component named CART and two children:

  • Filter, which represents a div where the user can select different criterias (color, size, gender...)
  • Products, which represents a list of shoes

CART.jsx

render() {
    console.log(this.props.filterCart, 'CART')
    const { products, error, pending } = this.props.products
    if (!this.shouldComponentRender()) return <LoadingSpinner />
    return (
        <section className="products_container">
            <Filter />
            {!this.shouldComponentRender() ? (
                <LoadingSpinner />
            ) : (
                <Products
                    products={products}
                    filterCart={this.props.filterCart}
                />
            )}
            {this.props.filterCart[0].value.length > 0 && <h1> hello </h1>}
        </section>
    )
}

const mapStateToProps = state => {
    return {
        products: state.products,
        filterCart: state.filter
    }
}

My CART component and Filter component are connected to my Redux store. Each time the users select a criteria in the Filter component, it becomes dispatched and updated in the reducer. My dispatches are set in the Filter component.

I put console.log(this.props.filterCart) in the render() in my CART and Filter components. What I noticed is that each time a criteria is selected, my Filter component logs the changes but the CART component doesn't. CART renders only logs one time and the output is an empty object. CART does not seem to be updated when a change has been made.

For my second test, I put this in CART & Filter:

{this.props.filterCart[0].value.length > 0 && <h1> hello </h1>}

Whenever a criteria is selected, my Filter displays "hello" as a criteria has been added to the initial empty array, but CART doesn't.

I did some research and apparently it could be due to the fact that I could have modified the initial state in the reducer, which is wrong. But, I am not sure because Filter reacts to the change.

This my reducer code :

Reducer.js

let filterCriteria = [
    {
        field: 'gender',
        value: []
    },
    {
        field: 'color',
        value: []
    }
]

const filter = (state = filterCriteria, action) => {
    switch (action.type) {
        case FILTER_CRITERIA.FILTER_PRODUCTS_BY_GENDER:
            if (action.indice === true) {
                state[0].value = state[0].value.concat(action.value)
            } else {
                state[0].value = state[0].value.filter(
                    element => element != action.value
                )
            }
            break

        case FILTER_CRITERIA.FILTER_PRODUCTS_BY_COLOR:
            if (action.indice === true) {
                state[1].value = state[1].value.concat(action.value)
            } else {
                state[1].value = state[1].value.filter(
                    element => element != action.value
                )
            }
            break
    }
    return state
}

Just to precise: when a criteria is chosen in the Filter (input box is checked), the criteria is added to the corresponding field. When I uncheck the box, it returns the filter without the value as expected. So, I don't have any concerns with my reducers regarding this matter.

My issues is why my second component doesn't re-render.

enter image description here

Do you have any idea what could be wrong?

Thank you very much!

9
  • 1
    Your reducer shouldn't have that much logic. It's definitely not a good practice! It is easy to get lost. It is possible that the state is not changing, in this case your component is not re-rendering. I'd suggest you to implement a lifecycle method to see what is happening. componentWillReceiveProps(nextProps) { console.log('nextProps', nextProps) } Commented Dec 15, 2019 at 18:57
  • Thank you for you answer but my state is actually changing. In Filter Component, when a criteria is chosen, it re-render automatically. Because through my console.log I can see the changes and the second test passed. But, Cart does not re-render so my Products Component doesn't get updated. Thank you for your reply and tips. Commented Dec 15, 2019 at 19:06
  • Your Product Component is a functional component or it is a class component. Would you please put the code here? Commented Dec 15, 2019 at 19:11
  • It's a class component but Products just received the props from CART component which are the datas from filterCriteria in my Store.redux. It just reflects the same issue from CART as it receives the props from there My issue is why CART doesn't re-render when my reducer get updated. Because if it does, it would have displayed my h1 as a second test {this.props.filterCart[0].value.length > 0 && <h1> hello </h1>} but it doesn't. Once, I resolve this, my props for Products will get updated so, it's not really the issue if you know what I meant. I am sorry if I lost you I am a beginner. Commented Dec 15, 2019 at 19:28
  • 1
    Don't be sorry to be a beginner, but to give up! I've had this issue already. Now I can understand you. Please, use state in your Cart.jsx and by the method componentWillReceiveProps you set the value from redux to your state and it will re-render for sure. Commented Dec 15, 2019 at 19:48

1 Answer 1

1

Hey check this codesandbox

React Redux example

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. I have used your approach for my reducer and I was able to see the change in my Cart Component. As I read and as your code confirms, I must have mutated directly my state in my previous reducer which leads to not re-rendering the component. Without your code and foremost your patience I couldn't have found the solution. Thanks as well for those who edited my post to make it clearer and even those who were thinking about the solution. Gaspar, thank you! God bless u

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.