About React Note
I'm currently working on an application using React.js. I've been meaning to learn this framework for a long time. So, it's a great opportunity to learn more and more about React while also making some real-world coins. React Note will be a series of writing about React software development. Tips, examples, best practices, anything that I find useful.
Enjoy!
Typechecking in React
You can use React.js with either Javascript or Typescript. If you decided to use Javascript, you'll know that Javascript lacks variable typechecking that Typescript has. However, you can utilize one of React's convenient typechecking system, that is PropTypes.
Here's the overview of what we'll be doing here:
- Preparation
- Import
PropTypes - Declare
propTypesproperty - Define property type
- Define required/optional and default value
- Define property's value range
- Advanced typechecking
1. Preparation
Throughout this guide, we will be using a React component named Product defined below. We will add typechecking to its properties: name and price. We will also add more properties as we go.
Important Note: To see typechecking in action, you need to open your browser's Inspection Tool. If typechecking sees an error, you'll see it in the console.
// Initial code.
import React from "react";
class Product extends React.Component
{
render()
{
return (
<div>
<h1>{this.props.name}</h1>
<p>Rp {this.props.price}</p>
</div>
);
}
}
export default Product;
2. Import PropTypes
Import prop-types to top of the file.
import React from "react";
// Add this new line.
import PropTypes from "prop-types";
3. Declare propTypes property
Declare propTypes property for the component before the export statement.
// ... rest of the code
// Add this new line before the export statement.
Product.propTypes =
{
// Your typechecking will be written here.
}
export default Product;
4. Define property type
Based on the type of property that will be typechecked, follow the questions below:
4.1. Is the property one of the following types: number, string, boolean, function, or symbol?
If yes, use one of the following:
Product.propTypes =
{
name: PropTypes.string, // string
price: PropTypes.number, // number
isEmpty: PropTypes.bool, // boolean
onClick: PropTypes.func, // function
symbol: PropTypes.symbol, // symbol
}
4.2. Is the property an array type?
If yes, you have two options: PropTypes.array and PropTypes.arrayOf().
Does the array's elements all have the same type?
- If yes, use
PropTypes.arrayOf(). Example:
Product.propTypes = { // sizes could only have type of string. // e.g., ["small", "medium", "large"] sizes: PropTypes.arrayOf(PropTypes.string), } - If not, use
PropTypes.array. Example:
Product.propTypes = { // sizes could have elements of different types. // e.g., [20, "medium", 30] sizes: PropTypes.array, }
4.3. Is the property an object type?
If yes, you have three options: PropTypes.shape(), PropTypes.objectOf(), and PropTypes.object.
Does the object have a specific shape?
- If yes, use
PropTypes.shape(). Example:
Product.propTypes = { // seller's property values must be an object with name and age property. // e.g., seller = { name: "Majid", age: 23 } seller: PropTypes.shape({ name: PropTypes.string, age: PropTypes.number, }), }
Does the object's property values all have the same type?
- If yes, use
PropTypes.objectOf(). Example:
Product.propTypes = { // seller's property values must be string // e.g., seller = { name: "Majid" } // or seller = { name: "Majid", age: "18-30" } seller: PropTypes.objectOf(PropTypes.string), } - If not, use
PropTypes.object. Example:
Product.propTypes = { // seller could be any object. // e.g., seller = { name: "Majid" } // or seller = { name: "Majid", age: 23 } seller: PropTypes.object, }
4.4. Is the property an instance of a class?
If yes, use PropTypes.instanceOf(). Example:
Product.propTypes =
{
// seller must be an instance of User class.
// e.g., seller = new User()
seller: PropTypes.instanceOf(User),
}
4.5. Is the property a React element?
If yes, use PropTypes.element. Example:
Product.propTypes =
{
// seller must be a React element
// e.g., seller = <Seller />
seller: PropTypes.element,
}
4.6. Is the property a node?
A node is defined as anything that can be rendered: numbers, strings, elements or an array (or fragments) containing these types.
If yes, use PropTypes.node. Example:
Product.propTypes =
{
// seller must be a node.
// e.g., seller = "Majid"
// or seller = <Seller />
seller: PropTypes.node,
}
4.7. Could the property have any type?
If yes, PropTypes.any. Example:
Product.propTypes =
{
// seller can be anything.
// e.g., seller = "Majid"
// or seller = { name: "Majid", age: 23 }
seller: PropTypes.any,
}
4.8. Could the property have many types?
If yes, PropTypes.oneOfType(). Example:
Product.propTypes =
{
// seller can be any of the following: a string, a User class instance, or a React element.
// e.g., seller = "Majid"
// or seller = new User()
// or sellet = <Seller />
seller: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(User),
PropTypes.element,
]),
}
5. Define required/optional and a default value
Is the property required or optional?
- If required, chain
isRequiredto the property. Example:
Product.propTypes = { // seller is now required. seller: PropTypes.any.isRequired, } - If not, does the property have a default value?
If yes, use defaultProps. Example:
Product.propTypes =
{
// price is optional.
price: PropTypes.number,
}
// Add this new line before the export statement.
Product.defaultProps =
{
price: 0, // If price is not provided, price will be 0
}
export default Product;
6. Define property's value range
Does the property have predefined values?
If yes, use oneOf(). Example:
Product.propTypes =
{
// size must have value of "small", "medium", or "large".
size: PropTypes.oneOf(["small", "medium", "large"]),
}
7. Advanced typechecking
You can define a custom validator for your element. For example, here we want to check the length of name property:
Product.propTypes =
{
name: function(props, propName, componentName) {
if(props.name.length > 255) {
return new Error(
`'${propName}' props in ${componentName} needs to have max. length of 255`
);
}
return null;
}
}
That's it!