Prop types

Our goal is to write truly reusable components, and to do that we have to define their interface in the clearest possible way.

If we want our components to be reused across the application, it is crucial to make sure that our components and their parameters are well-defined and straightforward to use.

With React, there is a powerful tool that lets us express, in a very simple way, the name of the props that a component expects to receive, and some validation rules for each one of them.

The rules relate to the type of property, as well as to whether the property is optional or required. There is also the option to write custom validation functions.

Since React 15.5.0, the PropTypes attributes are no longer part of the React core. Instead, you need to install a separate package called prop-types to use it.
npm install --save-dev prop-types

Let's start with a very simple example:

  import PropTypes from 'prop-types';

const Button = ({ text }) => <button>{text}</button>;

Button.propTypes = {
text: PropTypes.string
};

In the previous snippet, we created a stateless functional component that receives a text prop of the string type.

Great – now every developer that comes across our component knows how to use it in the right way.

However, adding the property only sometimes is not enough, because it does not tell us if the component works without the prop.

The button, for example, does not operate properly without text, and the solution is to mark the prop as required:

  Button.propTypes = { 
text: PropTypes.string.isRequired
};

If a developer uses the button inside another component without setting the text property, they receive the following warning in the browser console:

Failed prop type: Required prop `text` was not specified in `Button`.

It is important to say that the warning is emitted only in development mode. In the production version of React, the propTypes validation is disabled for performance reasons.

React provides ready-to-use validators for various numbers of types: from arrays, to numbers, to components.

It gives us also some utilities, such as oneOf, which accept an array of types that are valid for a particular property.

It is important to keep in mind that we should always try to pass primitive props to components, because they are simpler to validate and to compare (we will see the benefits in Chapter 10, About Testing and Debugging).

Passing single primitive props helps us to find whether a component surface is too wide and whether or not it should be split into smaller surfaces.

If we realize that we are declaring too many props for a single component, and they are not related to each other, it may be better to create multiple vertical components, each one with fewer props and responsibilities.

However, in some cases it is unavoidable to pass objects, and in those cases, we should declare our propType object using shapes.

The shape function lets us declare objects with nested properties and, for each one of those, we can define their types.

For example, if we are creating a Profile component that needs a user object with a required name and an optional surname, we can define it as follows:

  import { shape, string } from 'prop-types';

const Profile = ({ user }) => (
<div>{user.name} {user.surname}</div>
);

Profile.propTypes = {
user: shape({
name: string.isRequired,
surname: string
}).isRequired
};

If none of the existing React propTypes satisfies our needs, we can create a custom function to validate a property:

  user: shape({ 
age: (props, propName) => {
if (!(props[propName] > 0 && props[propName] < 100)) {
return new Error(`${propName} must be between 1 and 99`);
}

return null;
}
})

For example, in the preceding snippet, we verify whether the age field fits inside a certain range; and if it doesn't, an error is returned.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.233.43