3- Passing Data to Components

Got a slight problem which is really throwing me in the React course.

Having worked through, it seems some of the course is out of date, any plans to update?

Code below. I have four components in a Counters class. The value has been set. I think Mosh misses a step in his video.

I change the value to this.props.value, I then get ‘Cannot assign to read only property ‘value’ of object ‘#’’

So, I created a new let property counterValue to assign to the props value.

Still no luck. I will also post the Counters class code.

import React, { Component } from "react";

class Counter extends Component {
  state = {
    value: this.props.value,
tags: ["Tag1","Tag2"]
  }

   constructor() {
     super();
    this.handleIncrement = this.handleIncrement.bind(this);
    // handIncrement method needs to be binded to allow for 'this' keyword to have access to it globally.
    //  You can also use the arrow function to bypass the super and binding methods.
   }

  renderTags() {
    if (this.state.tags.length === 0) return <p>There are no tags!</p>;

    return (
      <ul>
        {this.state.tags.map(tag => (
          <li key={tag}> {tag} </li>
        ))}
      </ul>
    );
    // Gives a key value to each element in the array. React needs to be able to access each element.
  }

  
  //   handleIncrement() {}
  handleIncrement = () => {
    let counterValue = this.props.value
    this.setState({ value: (counterValue += 1) });
    console.log("Clicked")
    console.log(counterValue)
    // In React you need to set the state to update the view(UI). You cannot do it direct i.e this.state.count += 1 as a direct method.
  };

  getBadgeClasses() {
    let classes = "badge m-2 badge-";
    classes += this.props.value === 0 ? "warning" : "primary";
    return classes;
  }
  formatCount() {
    return this.props.value === 0 ? "zero" : this.props.value;
  }

  render() {
    return (
      <div>
        {/* {this.state.tags.length === 0 && "Please create new tags"}
                {/* Render a conditional statement in line - A populated string in JS is considered truthy, so both values are true */}

        <span
          style={{ fontWeight: "bold", fontSize: 15 }}
          className={this.getBadgeClasses()}
        >
          {this.formatCount()}
        </span>

        <button
          onClick={this.handleIncrement}
          className="btn btn-secondary btn-sm"
        >
          Increment
        </button>

        {this.renderTags()}
      </div>
    );
  }
}

export default Counter;

Counters class code.

    import React, { Component } from "react";
import Counter from "./counter";
import Paper from '@material-ui/core/Paper';
import shadows from "@material-ui/core/styles/shadows";
import extendedIcon from "@material-ui/core/styles/shadows";

class Counters extends Component {
  state = {
    counters: [
      { id: 1, value: 2 },
      { id: 2, value: 0 },
      { id: 3, value: 3 },
      { id: 4, value: 0 },
    ],
  };
  render() {
    return (
      <div>
        <Paper elevation={3} style={{padding: 20, margin:10,  }}>
        {  this.state.counters.map(counters => 
        <Counter key={counters.id} value={counters.value} /> ) }
        </Paper>
      </div>
    );
  }
}

export default Counters;

When I set the code base to Moshs’ I get “TypeError: Cannot read property ‘value’ of undefined”

A little stumped as I have spent a bit of time trying to rectify the fault myself.

From what I can see Counter component is working fine, so is the button. It seems to be something to do with setting the props.value which is causing an issue.

The use of value: this.props.value is not working for me either. Have you been able to find out a solution for the above?

1 Like

Make the following change in the constructor and it will work

state = {
    value: this.props.value
  };
  constructor(props){
    super(props)
    this.handleIncrement = this.handleIncrement.bind(this);
  }