Subscribe to my email list now at http://jauyeung.net/subscribe/
Follow me on Twitter at https://twitter.com/AuMayeung
Many more articles at https://medium.com/@hohanga
Even more articles at http://thewebdev.info/
React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.
Reduce the Use of Class Components
Class components have issues like dealing with lifecycle hooks and making sure the value of this
is the correct one.
With the introduction of React hooks, function components are now smart. Therefore, we can use function components like we did we with class components, but without the headache of this
and lifecycle hooks.
For instance, we can easily create a component that loads something from an API with the useEffect
hook as follows:
import React from "react";
export default function App() {
const [name, setName] = React.useState({});
const getName = async () => {
const res = await fetch("https://api.agify.io?name=michael");
setName(await res.json());
};
React.useEffect(() => getName(), []);
return <div className="App">{name.name}</div>;
}
In the code above, we have the React.useEffect
call to call an API to get some data on load. We set the data with the setName
function that’s returned from React.useState
, which returns a state variable and a function to set the state.
Then we display it in the div that we returned.
To do the same thing with class-based components, we’ve to write the following:
import React from "react";
export default class App extends React.Component {
constructor() {
super();
this.state = {};
}
async componentDidMount() {
const res = await fetch("https://api.agify.io?name=michael");
this.setState({ name: await res.json() });
}
render() {
return <div className="App">{this.state.name.name}</div>;
}
}
As we can see, it’s a bit longer. Also, we have to extend the React.Component
class to create a class component.
Also, we have to initialize this.state
in the constructor and also call super
.
In the componentDidMount
hook, which is the same as using useEffect
with an empty array as the second argument, we call the code to load the data that we want from the API.
Then we render the data in the render
method with the div as we did before, except that we’ve to reference this.state
to do that.
As we can see, the function component version is shorter. Also, we can use hooks however we see fit, unlike component lifecycle methods, which only run in certain parts of the lifecycle.
For instance, we can change the useEffect
hook to watch for input value changes and call the API as follows:
import React from "react";
export default function App() {
const [name, setName] = React.useState("");
const [result, setResult] = React.useState({});
const getName = async () => {
const res = await fetch(`https://api.agify.io?name=${name}`);
setResult(await res.json());
};
React.useEffect(() => {
getName();
return () => {};
}, [name]);
return (
<div className="App">
<input onChange={e => setName(e.target.value)} />
<p>{result.name}</p>
</div>
);
}
In the code above, we used the useEffect
hook to watch for the change of the value of name
by passing name
into the array of useEffect
as the second argument.
The return
statement in the useEffect
callback is for running any cleanup code if needed.
We then call getName
in a similar way as before, except that we interpolated name
in the URL. As we can see, the useEffect
hook does a lot more than a single lifecycle method in React can do. We did all that without having to reference this
, which is also great since it’s always confusing.
This is one more reason to use function components with hooks.
Don’t use Props in Initial State
We shouldn’t use props in the initial state because the constructor is called only once when the component is created.
This means that when we make some changes to props next time, the component state won’t be updated.
The better way to reference props is to do it in componentDidUpdate
. It’s a lifecycle method that lets us update the component when something change, such as when props change.
For instance, we can call this.setState
in componentDidUpdate
as follows:
import React from "react";
class Count extends React.Component {
constructor() {
super();
this.state = {
count: 0
};
}
componentDidUpdate(prevProps) {
if (this.props.count !== prevProps.count) {
this.setState({ count: this.props.count * 2 });
}
}
render() {
return <div>{this.state.count}</div>;
}
}
export default function App() {
const [count, setCount] = React.useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Count count={count} />
</div>
);
}
In the code above, we check if prevProps.count
‘s value is different from this.props.count
‘s the value before calling this.setState
so that we don’t call it repeatedly and unstoppably. Then we render this.state.count
that we set in the render
method.
This is the right because we’re updating the state according to the value of the prop. We should get the count displaying the count
prop passed in App
multiplied by 2.
If it’s in the constructor, then this.state.count
won’t update because it won’t update when the props change as we have in our example.
Conclusion
With the introduction of hooks, it’s time to embrace function components and hooks together to create stateful components. It reduces the headaches with dealing with lifecycle methods and the value of this
.
Also, if we’re using class components, then we have to remember not to set props as the value of a state property in the constructor, because the prop will never update the state after the first time the component loads. Instead, we should call setState
in componentDidUpdate
to update the state with our prop value.
The post React Tips — Modern Structures and State Updates appeared first on The Web Dev.