5

I'm having trouble understanding how to access props defined outside of a class component in React.

In the following code all props are defined except for this.props.checkboxArray which currently returns "cannot read property 'props' of undefined."

I know 'this' is not defined outside of the class component so I have tried binding 'this' to checkboxArray but still the same error that 'props' is undefined.

    let checkboxObject = this.props.checkboxArray.reduce(
      (name, boolean) => ({
        ...name,
        [boolean]: false
      }),
      {}
    );

    class CheckboxList extends Component {
      constructor(props) {
        super(props);
        this.state = { checkbox: checkboxObject };

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

      handleCheckboxChange = name => {
        let checkbox = this.state.checkbox;
        for (var key in checkbox) {
          if (key === name) {
            checkbox[key] = !checkbox[key];
          }
        }
        this.setState({ checkbox });
      };

      render() {
        return (
          <div className="row" id="CheckboxList">
            {this.props.checkBoxArray.map(checkbox => (
              <Checkbox
                label={checkbox}
                isSelected={checkboxObject[checkbox]}
                onCheckboxChange={this.props.onCheckboxTick}
                key={checkbox}
              />
            ))}
          </div>
    );
  }
}

export default CheckboxList;
ctb116
  • 65
  • 1
  • 5

2 Answers2

2

You no need to create checkboxObject outside component instead what you can do is that do the reduce of checkboxArray directly in constructor while initializing checkbox state like I did in below updated code. Then access it using this.state.checkbox[checkbox] to isSelected prop

This way you are initialing checkbox state only once Here is the updated code

    class CheckboxList extends Component {
  constructor(props) {
    super(props);
    this.state = { 
        checkbox: this.props.checkboxArray.reduce(
  (name, boolean) => ({
    ...name,
    [boolean]: false
  }),
  {}
); //here you can directly initialize the state
    };

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

  handleCheckboxChange = name => {
    let checkbox = this.state.checkbox;
    for (var key in checkbox) {
      if (key === name) {
        checkbox[key] = !checkbox[key];
      }
    }
    this.setState({ checkbox });
  };

  render() {
    return (
      <div className="row" id="CheckboxList">
        {this.props.checkBoxArray.map(checkbox => (
          <Checkbox
            label={checkbox}
            isSelected={this.state.checkbox[checkbox]}
            onCheckboxChange={this.props.onCheckboxTick}
            key={checkbox}
          />
        ))}
      </div>
);
  }
 }

  export default CheckboxList;
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
  • Or just create it as a function and pass props as parameter – Code Maniac Feb 22 '19 at 02:37
  • I wasn't very clear. I had the code above the class component because I only wanted it create the original object once. After that, I wanted the handleCheckboxChange method to be responsible for switching the booleans in the object. – ctb116 Feb 22 '19 at 02:58
2

You should create a function to call checkboxObject like:

const createCheckboxes =  checkboxArray => checkboxArray.reduce(
      (name, boolean) => ({
        ...name,
        [boolean]: false
      }),
      {}
    );

and call this funtion on your class component: createCheckboxes(this.props.checkboxArray)

Btw, this is not the best practice. Your checkbox should be editted on it's parent component using Selector

zmag
  • 7,825
  • 12
  • 32
  • 42
Vu Luu
  • 792
  • 5
  • 16
  • I agree this isn't best practice. Your solution worked but I ended up defining props in state which I believe is also bad practice. this.state = { checkbox: createCheckboxes(this.props.checkboxArray) }; This came about because, in my parent component, the key names from the object needed to be added to an array in state. However, I still needed the original object to toggle the checkbox ticks. – ctb116 Feb 22 '19 at 03:12