3 Core React Concepts Every Web Developer Should Understand
By: Amy J. Andrews
Tags: Reactjs, Codingbootcamp, Functional Programming, Javascript Development, React

3 Core React Concepts Every Web Developer Should Understand

There are many concepts you will learn in React. Below are three important core concepts you should understand no matter what.

Let’s get right into it.

1. Component Lifecycle

Component lifecycle is the core concept of React framework.

A React app consists of many individual components. Like everything in this world, each React component has its own lifecycle. That means they are born, start living, and then die at some point.

Each part of a component’s life is defined as a method. They are called at different stages while the component is existing.

Depending on what stage you’re handling, you will do certain tasks to serve specific purposes.

So, what are those stages?

1. componentWillMount()

This method is invoked before rendering. You use this method to get everything ready before displaying any UI element on the screen.

The component is not mounted yet. There’s no DOM in this stage. You shouldn’t make any asynchronous actions or change data using this.setState() . No need to rush, you will do all of them in the next stage.

2. componentDidMount()

After render() done for the first time, componentDidMount() function will be executed. This is when changes can occur.

Now, you can fetch data from API or update state.

To modify data in this stage, you can use setState() method, which will trigger another rendering.

3. componentWillRecieveProps()

This stage takes place right after the props are updated and before the next render() is executed.

4. shouldComponentUpdate()

You use this method to determine whether a component should be updated or not. The default value is true .

For the sake of performance, if you are sure that a component doesn’t need to be updated, then return false . That way it will remain the same as the previous state, no rendering happens.

5. componentWillUpdate()

This method will be invoked before rendering.

6. componentDidUpdate()

After rendering, this method will be called.

You can update DOM in this stage too. But remember to check prop changes from the previous state to make sure no infinite loop will occur.

7. componentWillUnmount()

When the component is unmounted from the DOM, this method will be called.

If there’s any resource you want to release, you should do it using this method.

2. setState()

After a React app initializes the UI, setState() is the only legitimate way to change the UI.

Let’s say we have a button that needs to be updated the label every time we click on it.

class Button extends React.Component {

constructor(props) {

super(props) this.state = {

buttonLabel: ‘On’

};

} render() {

return (

<div>

<button>{this.state.buttonLabel}</button>

</div>

)

}

}

The initial value of the button label is On , which is assigned to this.state.buttonLabel . We will add a function called toggleButton() and using setState() to update the value of buttonLabel .

toggleButton() {

this.setState({ buttonLabel: this.state.buttonLabel === ‘On’ ? ‘Off’ : ‘On’ });

}

Then we handle the click event of the button in render() function.

<button onClick={this.toggleButton.bind(this)}>

{ this.state.buttonLabel }

</button>

The whole implementation should be like below:

class Button extends React.Component {

constructor(props) {

super(props) this.state = {

buttonLabel: ‘On’

};

} toggleButton() {

this.setState({ buttonLabel: this.state.buttonLabel === ‘On’ ?

‘Off’ : ‘On’ });

} render() {

return (

<div>

<button onClick={this.toggleButton.bind(this)}>

{ this.state.buttonLabel }

</button>

</div>

)

}

}

When we click the button, the toggleButton() function will be called. Then the setState() function is executed to update the value of buttonLabel , which will trigger changing the UI.

You can also pass a function to setState() instead of an object.

toggleButton() {

this.setState((prevState, props) => {

return {

buttonLabel: prevState.buttonLabel === ‘On’ ? ‘Off’ : ‘On’}

}

);

}

So why pass a function instead of an object? Isn’t an object simpler?

Yes, an object is simpler.

But you have to understand that setState() doesn’t update the state immediately. It’s asynchronous. For better performance, React will batch multiple setState() calls into a single update. So, relying on the current state might lead to an unexpected result.

For example:

increase() {

// Initialize this.state.counter = 1

this.setState({counter: this.state.counter + 1});

this.setState({counter: this.state.counter + 1});

}

What result do you expect after increase() is called? this.state.counter === 3 , right? Except it’s not. The actual result of this.state.counter is 2 because those two setState() calls run asynchronous.

To fix it, pass a function to setState() . That function will take previous state as argument and it will queue the setState() calls so that they run in order.

increase() {

// Initialize this.state.counter = 1

this.setState((prevState, props) => {

return { counter: prevState.counter + 1 }

}); this.setState((prevState, props) => {

return { counter: prevState.counter + 1 }

});

}

This time, this.state.counter is 3 as expected.

So, when you use the current state to set the new state like the two examples above, you should pass a function. Otherwise, pass an object for simpler.

3. Higher-Order Components

You might hear the concept of higher-order functions in functional programming. It’s a function that takes other functions as arguments and returns a function as its result.

When it comes to React, we have a similar concept, higher-order components. It’s a function that takes a component and returns a new component.

This concept offers you the ability to create a new extended component based on the existing ones which we will keep the original logic of them.

For example:

// LoadingHOC.jsx

const addLoader = (data) => (WrappedComponent) => {

return class LoadingIndicator extends React.Component {

render() {

return data === null

? <Loader />

: <WrappedComponent { ...this.props }/>

}

}

} // UserList.jsx

class UserLoader extends React.Component {

render() {

return (

<UserListWithLoadingIndicator users={this.state.users} />

);

}

} const UserList = ({ users }) => {

return (

<div>

{ /* show users */ }

</div>

);

} const UserListWithLoadingIndicator = addLoader(‘users’)(UserList);

In the simple HOC example above, we check whether the data is available or not. If it’s empty, we show a loading indicator until the data is updated.

HOC is really useful as it allows us to extend an existing component by adding extra features to it. It’s like a minimal version of adding plugins to a Wordpress-based blog.

Conclusion

So, did you get all the points above?

They are the basis concepts in React you should understand clearly before digging deeper into this framework.

Last but not least, stay updated with the official documentation because it changes constantly. Even some lifecycle methods get deprecated now. Since the first time I got into this great framework in 2016, it’s kept evolving and growing. It’s more mature now.

Enjoyed this article? If so, get more similar content by subscribing to Decoded, our YouTube channel!