Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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] }

like image 319
Anna Avatar asked Oct 28 '22 21:10

Anna


1 Answers

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],
  }
like image 192
Muhammet Enginar Avatar answered Nov 09 '22 16:11

Muhammet Enginar