0

import React from 'react';
import ReactDOM from 'react-dom';

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  changeColor = () => {
    this.setState({color: this.getRandomColor()});
  }
  
  clr = function() {
        var hex = Math.floor(Math.random()*256).toString(16);
        return ("0"+String(hex)).substr(-2); // pad with zero
  }
    
  getRandomColor = function() {
    //return "#"+this.clr()+this.clr()+this.clr();  //referenceError: clr is not defined
    //return "#"+clr()+clr()+clr(); // Failed to compile: 'clr' is not defined
    return "#"+{this.clr}+{this.clr}+{this.clr}; // Failed to compile: Unexpected keyword 'this' 
  }

  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>It is a {this.state.color} {this.state.model} from {this.state.year}. </p>
        <button
          type="button"
          onClick={this.changeColor}
        >Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Car />, document.getElementById('root'));

I'm learning React from a tutorial, and I'm trying to tweak the function to generate a random color for the car. I've tried to call the clr function, and included my failed efforts for review. How do I correctly call the clr function?

Below is the revision I came up with. I will continue with learning Reactjs!

import React from 'react';
import ReactDOM from 'react-dom';

class Car extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      brand: "Ford",
      model: "Mustang",
      color: "red",
      year: 1964
    };
  }
  changeColor = () => {
    this.setState({color: this.getRandomColor()});
  }
  
  getRandomColor = function() {
        var num = Math.floor(Math.random()*6) + 1;
        switch (num) {
            case 1:
                return ("yellow");
                break;
            case 2:
                return ("purple");
                break;
            case 3:
                return ("orange");
                break;
            case 4:
                return ("blue");
                break;
            case 5:
                return ("black");
                break;
            case 6:
                return ("green");
                break;  
        }
  }  

  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>It is a {this.state.color} {this.state.model} from {this.state.year}. </p>
        <button
          type="button"
          onClick={this.changeColor}
        >Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Car />, document.getElementById('root'));
James Z
  • 12,209
  • 10
  • 24
  • 44
JuniorDev
  • 5
  • 3
  • Did you mean `return "#" + this.clr() + this.clr() + this.clr();` ? – Jonas Wilms Feb 03 '21 at 22:43
  • `{` ... `}` in this context is used to build up objects, like `{ user: "JuniorDev", question: "JavaScript ..." }`. The `{this.clr}` therefore does not quite work. (There are also so called "template literals" which also use curly brackets, but their syntax is also quite different) – Jonas Wilms Feb 03 '21 at 22:45
  • Jonas, yes.. I did try return "#" + this.clr() + this.clr() + this.clr(); but I got a reference error for that. It is commented out in my post – JuniorDev Feb 03 '21 at 22:55
  • For debugging purposes, it would be much easier to separate them into three assignment statements. Then perhaps a forth assignment that is a concatenation of them. I would make it easier on you. – Randy Casburn Feb 03 '21 at 23:02
  • Ok. I changed `changeColor = () => ` to `changeColor = function()`, and used `return "#"+this.clr()+this.clr()+this.clr();` in the getRandomColor function. However, that results in **TypeError: Cannot read property 'setState' of undefined**. – JuniorDev Feb 03 '21 at 23:04
  • It may be worth looking at more modern React tutorials, even better is to read through the react 'Main concepts' section (https://reactjs.org/docs/components-and-props.html) so you can get used to making functional components. – Michael Bauer Feb 03 '21 at 23:07
  • you have issues dealing with this, ending up in execution context somewhere. move all as arrow functions () => {} plus in the constructor bins this on the methods e.g. this.changeColor = this.changeColor.bind(this) – quirimmo Feb 03 '21 at 23:14
  • I have tried your code with the first 'attempt' at using clr() activated: `return "#" + this.clr() + this.clr() + this.clr();` and at least for me, it compiles and runs just fine. Tested with React v16.12.0 + npm v6.14.10 + Nodejs v14.15.4. – Peter B Feb 03 '21 at 23:26

2 Answers2

2

It appears that you have confounded JSX's expression delimiter {} with JavaScript's String literal syntax ${...}.

The fix is quite easy. In your working code,

Change:

return "#"+{this.clr}+{this.clr}+{this.clr};

To:

return `#${this.clr()}${this.clr()}${this.clr()}${this.clr()}`; 

Note the use of backticks, the removal of the + and addition of ().

I also included the fourth pair of hex values as I think you'll have better success if you use the full set.

Here is a working StackBlitz

Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
0
  changeColor = () => {
    this.setState({color: this.getRandomColor()});
  }
  clr = function() {
        return Math.floor(Math.random()*256).toString(16);
  }
  getRandomColor = function() {
    return `#${this.clr()}${this.clr()}${this.clr()}`;
  }

  render() {
    return (
      <div>
        <h1>My {this.state.brand}</h1>
        <p>It is a {this.state.color} {this.state.model} from {this.state.year}. </p>
        <button
        style={{color: this.state.color}}
          type="button"
          onClick={this.changeColor}
        >Change color</button>
      </div>
    );
  }
Shweta patel
  • 105
  • 11