Anna
Anna

Reputation: 3141

React/Redux component with checkboxes does not update when click on checkbox

In my component I have checkboxes. When I click on them I want save selected checkbox in redux state and update my component so selected checkbox should shown as checked. So this is my component:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {selectIngredient} from '../actions';
class Ingredient extends Component {
    constructor(props) {
        super(props)
        this.isSelected = this.isSelected.bind(this);
        this.handleCheckbox = this.handleCheckbox.bind(this);

    }


    handleCheckbox(e) {
        const value=e.target.value;
        this.props.selectIngredient(value);
    }


    isSelected(id) {
        return (this.props.selectedIngredients.indexOf(id) > -1)
     }

    render() {
        return (
            <div className="container">
                <div className="form-check checkbox">
                    <label className="form-check-label">
                        <input checked={this.isSelected(1)}
                               className="form-check-input"
                               onClick={this.handleCheckbox}
                               type="checkbox" value="1" />
                        1
                    </label>

                </div>
                <div className="form-check checkbox">
                    <label className="form-check-label">
                        <input checked={this.isSelected(2)}
                               className="form-check-input"
                               onClick={this.handleCheckbox}
                               type="checkbox" value="2" />
                        2
                    </label>

                </div>
                <div className="form-check checkbox">
                    <label className="form-check-label">
                        <input checked={this.isSelected(3)}
                               className="form-check-input"
                               onClick={this.handleCheckbox}
                               type="checkbox" value="3" />
                       3
                    </label>

                </div>
            </div>
        );
    }
}

function mapStateToProps(state, ownProps){
    const {selectedIngredients} = state;
    return {selectedIngredients}

}

export default connect(mapStateToProps,{selectIngredient})(Ingredient);

And this is action/index.js

import {SELECT_INGREDIENT} from "../constants";

export function selectIngredient(selected){
    const action = {
        type: SELECT_INGREDIENT,
        selected
    }
    return action;
}

And here is reducer:

import {SELECT_INGREDIENT} from "../constants";

export default (state={selectedIngredients:[]}, action)=>{
    let stateBefore = Object.assign({},state);
    switch(action.type){
        case SELECT_INGREDIENT:
            const {selected} = action;
            stateBefore['selectedIngredients'].push(+selected);
            return stateBefore

        default:
            return state;
    }

} 

When I click on checkboxes nothing changes, they stay empty. Component is not updating. But redux updating its state. I thought if redux state is updating so should the component and its checkboxes. Is it wrong?

Please help me figure out how to make this work. Thank you


The answer given in the comments below:

in your reducer return { ...state, selectedIngredients: [...state.selectedIngredients, action.selected] }

Upvotes: 5

Views: 2327

Answers (1)

Muhammet Enginar
Muhammet Enginar

Reputation: 516

This is a mutation:

  let stateBefore = Object.assign({},state);
  ...
      stateBefore['selectedIngredients'].push(+selected);

You are shallowly copying the state object but you still mutate the selectedIngredients because it is copied by reference so you are still modifying the existing selectedIngredients object.

Check the first answer to following issue https://github.com/reactjs/redux/issues/1769

use object spread operator:

case SELECT_INGREDIENT:
  return {
    ...state, 
    selectedIngredients: [...state.selectedIngredients, action.selected],
  }

Upvotes: 2

Related Questions