TIL - Classes & React Components

What follows is notes from a class. Incomplete thoughts & code that probably will only make sense to me. Given enough time, even that may be a stretch! Reference at your own risk 😂

  • An object is an instance of a class
  • Classes can be extended
  • For React to work in Codepen, add react, react-dom, and Babel as the preprocessor in Codepen settings

Slides

Basic Stateless Component

function FirstComponent() {
return <h1>Hiya</h1>;
}

const mountNode = document.getElementById('root');

// ReactDOM render takes two arguments: what to render and where to render it
ReactDOM.render(<FirstComponent />, mountNode);

Basic Stateless Component With Props

function FirstComponent(props) {
return <h1>Hiya {props.name}</h1>;
}

const mountNode = document.getElementById('root');

// ReactDOM render takes two arguments: what to render and where to render it
ReactDOM.render(<FirstComponent name='Nia' />, mountNode);

React Fragments no longer require the Fragment keyword

Empty angle brackets do the same job. This is because the render method can only take one element to render, so if you need to render multiple components, they need to be wrapped in a single fragment.

ReactDOM.render(
<>
<FirstComponent name="Nia" />
<FirstComponent name="Shelly" />
</>, mountNode
);

React can only return and render a single element.

React Props Can Be Hard Coded Or Evaluated

function FirstComponent(props) {
return (
<div>
<h1>Hiya {props.name}. You are {props.age}.</h1>
<h2>BOOM!</h2>
</div>
);
}

const mountNode = document.getElementById('root');
const barryAge = 11 * 8 - 1;

// ReactDOM render takes two arguments: what to render and where to render it
ReactDOM.render(
<>
<FirstComponent name="Nia" age='87' />
<FirstComponent name="Shelly" age={11 * 9 - 12} />
<FirstComponent name="Barry" age={barryAge} />
</>, mountNode
);

Output:

Hiya Nia. You are 87.

Hiya Shelly. You are 87.

Hiya Barry. You are 87.

React Context API

This seems pretty useful—check it out!

Two Adjacent Counter Components

When components need state they are set up as a class instead of a function.

class Counter extends React.Component {
constructor(props){
super(props);
this.state = {
count: 0
};
// you have to bind 'this' to new methods when you create them because React
this.increment = this.increment.bind(this);
}

increment(){
// wrap the arrow function in parentheses to make sure it returns an object instead of running this as a function
this.setState((prevState) => ({
count: prevState.count + 1
}))
}

render() {
return(
<div>
<h1>Current count is {this.state.count}</h1>
<button onClick={this.increment}>+</button>
</div>
)
}
};

const mountNode = document.getElementById('root');

ReactDOM.render(
<>
<Counter />
<Counter />
</>, mountNode
);

React Component Lifecycle Methods

There are some methods in React.Component by default: construction –> pre-render –> render –> post-render (aka birth, life, and death methods). Read about them in the React docs.

When a React component is extended, your own methods will overwrite the defaults. This is called method overload. Example:

class Timer extends React.Component {
// extend a basic React component and get all its props and methods by running super
constructor(props) {
super(props);
// set state to an object (it doesn't have to be but that's convention)
this.state = {
secondsElapsed: 0
};
}

tick() {
// setState needs to be an object or return an object. It's the ONLY method of updating state in the component. Wrap the arrow function in parentheses to make sure it returns an object instead of running this as a function.
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
// It's not possible to set state as an object (you can only do this in the constructor)...the above is best practice. Example:
// this.state = {
// status: active
// }
}

componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}

componentWillUnmount() {
clearInterval(this.interval);
}

render() {
// Render is the only required method in a React component
return <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
}
}

Key Takeaways:

  • componentDidMount() is the go-to method for doing things with your component knowing it’s loaded & ready on the page
  • componentWillUnmount() is the go-to method for scrapping anything you’ve set up in the component which will take memory. React scraps the component when it’s no longer needed but it doesn’t automatically scrap things the component did so this must be done manually with componentWillUnmount. In the above example the timer would just keep running forever otherwise.