0

I have problem with react-redux. I create a checkbox with redux, but i have a problem that my data=[array] back data=[array] but not [new array] with new props "completed". When i use this function on reducer, i have problem with my ComponentBike this.props.state.map inspector says: Cannot read property 'map' of undefined. What am I doing wrong, people?

This is my reducer:

import { TOGGLE_CHECKBOX } from '../actions/actions'

export default function reducer(state = [], action) {
switch (action.type) {
    case 'TOGGLE_CHECKBOX':
        return {
            ...state,
            checkbox: state.checkbox.map(check => check.id === action.id ?
                {...check, completed: action.completed} :
            check
            )
        };
}
}

This is my action:

export const TOGGLE_CHECKBOX = 'TOGGLE_CHECKBOX';

export function toggleCheckbox(id) {
 return  {
  type: TOGGLE_CHECKBOX,
  completed: true,
  id
}
}

My Container:

import React from 'react';
import { connect } from 'react-redux';
import { toggleCheckbox } from '../../redux/actions/actions';
import ComponentBike from '../../components/bikes/info-bikes';

function mapStateToProps(state) {
return {
     state: state
  };
}

function mapDispatchToProps(dispatch) {
return {
    onChange: (id) => dispatch(toggleCheckbox(id)),
  }
}
const CheckboxContainer = connect(mapStateToProps, mapDispatchToProps)(ComponentBike);

export default CheckboxContainer;

My store:

import { createStore } from 'redux';
import reducer from '../reducers/reducer';

export const initialState = {
'checkbox': [
{
        'id': 1,
        'label': 'Sport',
        'completed': false
    },
    {
        'id': 2,
        'label': 'Cross',
        'completed': false
    }
]

const store = createStore(reducer, initialState);

export default store;

and my component:

import React from 'react';
import Checkbox from '../../../../Checkbox';

export default class ComponentBike extends React.Component {
constructor(props) {
    super(props);


    this.handleClick = this.handleClick.bind(this);
}

handleClick() {
     this.props.onChange(this.props.id);
}

render () {
    return <div className="window">
                    <Container>
                        <div className="all-checks">
                            {this.props.state.map(check =>
                                <Checkbox
                                    key={check.id}
                                    id={check.id}
                                    label={check.label}
                                    checked={check.completed}
                                    onChange={this.handleClick(check.id)}
                                />
                            )}
            </div>

I would be very grateful for help with this problem.

1 Answers1

0

If you look at your state object, you can see the checkboxes are inside the checkbox property:

export const initialState = {
  'checkbox': [

So that would be the array you need to loop through in the render function (this.props.state.checkbox.map):

<div className="all-checks">
  {this.props.state.checkbox.map(check =>
    <Checkbox
      key={check.id}
      id={check.id}
      label={check.label}
      checked={check.completed}
      onChange={this.handleClick(check.id)}
    />
  )}
</div>

Update

I see a few other problems that might be causing some trouble. I renamed checkbox to checkboxes since it's an array. Here are some changes I would make below:

reducer

initialState goes better with the reducer, because at some point you might have multiple reducers that can each have their own initial state (see here). Also make sure you have a default case in the switch statement:

const initialState = {
  checkboxes: [
    {
      id: 1,
      label: 'Sport',
      completed: false
    },
    {
      id: 2,
      label: 'Cross',
      completed: false
    }
  ]
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
  case 'TOGGLE_CHECKBOX':
    return {
      ...state,
      checkboxes: state.checkboxes.map(check => check.id === action.id ?
        {...check, completed: action.completed} :
        check
      )
    };
  default:
    return state;
  }
}

store

const store = createStore(reducer);

container

Pass the part state you need explicitly:

function mapStateToProps(state) {
  return {
     checkboxes: state.checkboxes
  };
}

component

onChange needs an arrow function to pass the correct id

handleClick(id) {
  this.props.onChange(id);
}

render() {
  return (
    <div className="window">
      <Container>
        <div className="all-checks">
          {this.props.checkboxes.map(check => (
            <Checkbox
              key={check.id}
              id={check.id}
              label={check.label}
              checked={check.completed}
              onChange={() => this.handleClick(check.id)}
            />
          ))}
        </div>
      </Container>
    </div>
  );
}

Update 2

Needed to add default to the switch statement in the reducer.

  switch (action.type) {
  case 'TOGGLE_CHECKBOX':
    return {
      ...state,
      checkboxes: state.checkboxes.map(check => check.id === action.id ?
        {...check, completed: action.completed} :
        check
      )
    };
  default:
    return state;
  }

See working fiddle here https://jsfiddle.net/t7smqtbL/1/

Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • Thanks for this, but inspector now says: "Cannot read property 'checkbox' of undefined" /../components/bikes/info-bikes.js:66 – Audi Quattro 1992 Nov 27 '17 at 08:36
  • @AudiQuattro1992 added some more info and changes that might help you – Austin Greco Nov 27 '17 at 20:20
  • I dont understand, where is my trouble. Now insperctor give me new issue: "Cannot read property 'checkboxes' of undefined" /CheckboxContainer/ checkboxes: state.checkboxes What is wrong? – Audi Quattro 1992 Nov 27 '17 at 21:00
  • @AudiQuattro1992 looks like it was causing an error because there was no `default` in the switch statement. Try adding that and it should work. I also added a working jsfiddle demo – Austin Greco Nov 27 '17 at 21:32
  • THANK YOU MAN !!! From my heart, god bless you and your family!))) Thank you very much! – Audi Quattro 1992 Nov 27 '17 at 22:07