Select Page

From Codecademy. 

https://snippets.cacher.io/snippet/30af67f4aa8a9469dd29 

App Functionality

User clicks on a button to randomly change the background color of an otherwise blank screen.

App parts

We only worked on Random.js and its child component Button.js
Other components in the project are Random.compiled.js ; index.html ; styles.css

Functionality and connectedness of app parts

Random.js imports { Button } from ‘./Button.js’
Random.js consists of a long class component Random, and a ReactDom.render
Button.js renders a button element. Via props, it lets Random.js know when the button has been clicked. Via props, Random.js lets it know if the color will be light or dark (light color and the css class on Button.js selects a dark-colored button; otherwise, it selects a light-colored button).

Random

class component Random has the following methods and parameters:
constructor(props) that contains super(props), this.state = { color: [19, 40, 100] }; & this.handleClick = this.handleClick.bind(this):
componentDidMount() that calls this.applyColor();
componentDidUpdate(prevProps, prevState) that also calls this.applyColor();
formatColor(ary) that returns rgb(‘ + ary.join(‘, ‘) + ‘)’;
isLight() that contains const rgb = this.state.color; and returns rgb.reduce((a,b) => a+b) < 127 * 3;
applyColor() that contains const color = this.formatColor(this.state.color); & document.body.style.background = color;
chooseColor() that contains const random = []; &

for (let i = 0; i < 3; i++) {
random.push(Math.floor(Math.random()*256));
}

and returns random;

handleClick() that contains this.setState( {color: this.chooseColor()});

& the render method, which renders the following code:

<h1 className={this.isLight() ? ‘white’ : ‘black’}>
Yourcoloris{this.formatColor(this.state.color)}.
</h1>
<Button onClick={this.handleClick} light={this.isLight()}/>
</div>
);
}

Button

Button.js contains only the following code:

export class Button extends React.Component {
render() {
return (
<button
onClick={ this.props.onClick }
className={ this.props.light ? ‘light-button’ : ‘dark-button’ }>
Refresh
</button>
);
}
}

Button.js is the child component of Random.js

Button.js receives the onClick and the light props from Random.js 
Via the onClick prop, Button.js tells Random.js when it is clicked, which tells the onClick handler method in Random.js to act
Button.js is told by Random.js via the light prop whether the displayed background color is light or dark. And Button.js uses that information to set the css class to ‘light-button’ or ‘dark-button’

Most of the action takes place in Random.js
Next we’ll go through all the methods inside of Random.js

constructor(props) {
super(props);
this.state = { color: [23, 58, 100] }
this.handleClick = this.handleClick.bind(this);}

I don’t know why you have to put super(props); inside the constructor(props)
All stateful components need constructors because the states have to be initialized.

this.state sets the color variable to an array of numbers within the RGB spectrum

Since handleClick will be used as an event handler, we will pass its functionality to a child component. (Button, in this case)
If we call the method from Button, this will refer to Button, but we want it to refer to the Random class, not the Button class
Because color is part of the Random class
this can refer to different objects, based on contexts; when we bind the Random class to handleClick, every this in handleClick will refer to Random

We are setting the handleClick method equal  to a version of itself that is bound to this object, which is Random
So now the keyword this inside of handleClick will always refer to Random class, even if we call it from Button class.

componentDidMount() {this.applyColor();}

componentDidMount() is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
https://reactjs.org/docs/react-component.html 

componentDidUpdate(prevProps, prevState) {this.applyColor():}

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.

Use this as an opportunity to operate on the DOM when the component has been updated. This is also a good place to do network requests as long as you compare the current props to previous props (e.g. a network request may not be necessary if the props have not changed).

prevProps and prevState don’t appear anywhere else in the code.

I don’t know why they had to be used here.

formatColor(ary) return ‘rgb(‘ + ary.join(‘, ‘) + ‘)’;

This method takes three numbers in an array and returns rgb(first number, second number, third number)
It works because calling .join on an array returns a string with the chosen delimiter (in this case a comma with a space after it)

The formatColor(ary) method is called by the applyColor method, which uses the color state to return a color variable, which is then used to set the document’s body’s background color.

isLight() {
                const rgb = this.state.color;
                return rgb.reduce((a,b) => a+b) < 127 * 3);

I don’t understand how this works. 
The reduce() method executes a user-supplied “reducer” callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.
In this case does it just add up all the elements in the array?
How is this returning a True or False value? Why 127 * 3?
This https://www.nbdtech.com/Blog/archive/2008/04/27/calculating-the-perceived-brightness-of-a-color.aspx  doesn’t seem to help