Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
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.
Set isRequired on a Prop if Another Prop is null or Empty with Prop-Types
Prop-types lets us validate another prop with custom validation.
For instance, we can write:
import PropTypes from 'prop-types';
//...
Item.propTypes = {
showDelete: PropTypes.bool,
handleDelete: (props, propName, componentName) => {
if (props.showDelete === true && typeof props[propName] !== 'function') {
return new Error('handleDelete must be a function');
}
},
}
We have the Item
component where we set the propTypes
property to do some validation.
We have showDelete
set to a boolean prop.
And handleDelete
is validated by a function that checks if the showDelete
prop is true
and that the handleDelete
prop is a function.
propName
is the name of the prop that we’re currently validating.
So propName
is the handleDelete
prop.
We make sure that if props.showDelete
is true
, the handleDelete
prop is a function.
There’s also the react-required-if package that lets us simplify our code.
For instance, we can write:
import requiredIf from 'react-required-if';
import PropTypes from 'prop-types';
//...
Item.propTypes = {
showDelete: PropTypes.bool,
handleDelete: requiredIf(PropTypes.func, props => props.showDelete === true)
};
We make sure that handleDelete
is a function when showDelete
is true
with the requiredIf
function.
Wrong Components in a List Rendered by React
If we’re rendering a list of items, we should assign a unique value for the key
prop to each item in the list.
For instance, we can write:
<div>
<div className="packages">
<div key={0}>
<button>X</button>
<Package name="a" />
</div>
<div key={1}>
<button>X</button>
<Package name="b" />
</div>
<div key={2}>
<button>X</button>
<Package name="c" />
</div>
</div>
</div>
We have a list of items, and we assigned a unique value for each key
prop.
This way, they’ll be rendered properly no matter what we do with them.
If we’re rendering an item, we should write:
consr packages = this.state.packages.map((package, i) => {
return (
<div key={package}>
<button onClick={this.removePackage.bind(this, package)}>X</button>
<Package name={package.name} />
</div>
);
});
We make sure that we pass in a unique value for the key
prop.
Then when we manipulate the array and re-render it, everything will be rendered properly.
We should never use the array index as the key since they can change and may not be unique.
How to Create an App with Multiple Pages using React
To let us create an app that has multiple pages in React, we’ve to use React Router to do the routing.
We install it by running:
npm install react-router-dom
Then we write:
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
const Home = () => {
return <h2>Home</h2>;
}
const About = () => {
return <h2>About</h2>;
}
const Profile = () => {
return <h2>Profile</h2>;
}
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/profile">
<Profile />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
We created 3 function components which we use as the route’s content.
Then in the App
component, we import the Switch
component and add the routes inside.
The Route
component lets us create the routes.
path
is the URL path that we want to map to the component.
And we add the component we want to display inside the Route
component.
Link
is provided by React Router so that we go to the URL that we want to go to.
It can also work with nested routes, custom links, default routes, query strings, and URL parameters.
We can add nestyed routes by writing:
loads the Topics component, which renders any further <Route>'s conditionally on the paths :id value.import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<Switch>
<Route path="/topics">
<Topics />
</Route>
</Switch>
</div>
</Router>
);
}
function Topics() {
let match = useRouteMatch();
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to='about'>About</Link>
</li>
</ul>
<Switch>
<Route path='/about' >
<About />
</Route>
</Switch>
</div>
);
}
function About() {
return <h2>About</h2>;
}
We just nest routes in components to nest them.
Conclusion
We create an app that has multiple pages with React Router.
Also, we can conditionally validate props with a function or a 3rd party library.
And we should always add a key
prop with a unique value to each list item.