React is a popular library for creating web apps and mobile apps.
In this article, we’ll look at some tips for writing better React apps.
How to Force a Function Component to Render
We can force a function component to render with the use-force-update package.
To install it, we run:
npm install use-force-update
or:
yarn add use-force-update
Then we can use it by writing:
import useForceUpdate from 'use-force-update';
const App = () => {
const forceUpdate = useForceUpdate();
const rerender = () => {
console('rerendering');
forceUpdate();
};
return <button onClick={rerender} />;
};
We get the useForceUpdate
hook to return the forceUpdate
function that lets us update whenever we want.
Also, we can set a state to make a React component update.
For instance, we can write:
import React, { useState } from 'react';
function useForceUpdate(){
const [value, setValue] = useState(0);
return () => setValue(value => ++value);
}
function App() {
const forceUpdate = useForceUpdate();
return (
<div>
<button onClick={forceUpdate}>
re-render
</button>
</div>
);
}
We created our own useForceUpdate
hook to update a value
state.
The useState
hook returns a state variable and a function to update it.
Whenever we update a state, React will render the component again.
componentDidMount Equivalent in a React Function Component
The equivalent of componentDidMount
in a function component is the useEffect
hook with an empty array.
For instance, we can write:
useEffect(() => {
//...
}, []);
to make the code in the callback only load when the component mounts.
We can also pass in variables to the array to watch those values for changes:
useEffect(() => {
//...
}, [foo, bar]);
The content can be any value like states, props, etc.
Detect Route Change with React Router
We can detect route change with React Router with the history.listen
method.
For instance, we can write:
history.listen((location, action) => {
console.log(location, action);
})
location
is the native location object that has all the URL data like the pathname
for the pathname.
search
for the query string.
hash
for the string after the hash.
action
has the name for the navigation action.
Setting State on componentDidMount()
Setting state in the componentDidMount
method isn’t an antipattern.
It’s a recommended practice for setting state when the component mounts.
For instance, we can use it to get API data and set the state:
componentDidMount() {
fetch("https://randomuser.me/api")
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
user: results[0]
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
We get the data from an API with the fetch API.
Then we get the resulting data in the first then
callback to set the state for the data.
In the 2nd callback, we set the isLoaded
state to false
and an error
state.
Use if…else… Statement in React render Function
There are a few ways to display things conditionally with React.
We can use various boolean expressions to do so.
For example, we can write:
render() {
const { isLoggedIn } = this.state;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleClick} />
) : (
<LoginButton onClick={this.handleClick} />
)}
</div>
);
}
We get the isLoggedIn
state and use that to check the if the user is logged in.
If the user isn’t then we return LogoutButton
.
Otherwise, we return LoginButton
.
We can also use an if-else statement to assign a component to a variable/
For instance, we can write:
render() {
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleClick} />;
} else {
button = <LoginButton onClick={this.handleClick} />;
}
return (
<div>
{button}
</div>
);
}
We check isLoggedIn
with an if-else statement instead of a ternary expression.
We assigned our components to the button
variable and render that instead of writing everything inline.
This lets us write longer expressions in a conditional statement.
Also, we can use the &&
operator to display things given a condition.
For example, we can write:
render() {
return (
<div>
{cartItems.length > 0 &&
<h2>
You have {cartItems.length} in the cart.
</h2>
}
</div>
);
}
If cartItems.length > 0
is true
then the stuff that comes after it is rendered.
Conclusion
We can force a component to render in various ways.
Also, we can display things conditionally with several kinds of statements and expressions.
And we can use history.listen
to listen for changes in React Router.