迷いはもう不要!Reactの型検証、objectOfとshapeを使いこなして安心・安全なコードへ
React PropTypes: objectOf vs shape の分かりやすい解説
PropTypes
には、様々な型検証方法がありますが、その中でもよく使用されるのがobjectOf
とshape
です。一見似ているように見えますが、それぞれの役割と使い分けが異なります。
objectOf
objectOf
は、プロパティの型のみを検証します。つまり、オブジェクト内のプロパティ名が何であっても、指定された型であるかどうかだけをチェックします。
import PropTypes from 'prop-types';
const MyComponent = ({ colors }) => {
return <div style={{ backgroundColor: colors.primary }}>
{colors.secondary}
</div>;
};
MyComponent.propTypes = {
colors: PropTypes.objectOf(PropTypes.string),
};
上記の例では、colors
プロパティはオブジェクトであること、そしてその中のすべてのプロパティが文字列であることが検証されます。プロパティ名がprimary
であってもsecondary
であっても、問題ありません。
shape
一方、shape
は、オブジェクトの構造を検証します。つまり、オブジェクト内のプロパティ名とその型を個別に定義することができます。
import PropTypes from 'prop-types';
const MyComponent = ({ user }) => {
return (
<div>
{user.name} - {user.age}
</div>
);
};
MyComponent.propTypes = {
user: PropTypes.shape({
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
}),
};
上記の例では、user
プロパティはオブジェクトであること、そしてその中にname
とage
というプロパティが存在し、それぞれが文字列と数値であることが検証されます。プロパティ名の順序は重要ではありません。
使い分け
objectOf
とshape
の使い分けは以下の通りです。
- プロパティ名の順序が重要でない場合
shape
を使用します。 - プロパティ名の自由度が必要な場合
objectOf
を使用します。 - オブジェクトの構造を検証したい場合
shape
を使用します。
一般的には、プロパティの構造を明確に定義したい場合はshape
を使用するのがおすすめです。一方、プロパティ名の自由度が必要な場合や、単純にプロパティの型だけを検証したい場合はobjectOf
を使用します。
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({ colors }) => {
return (
<div style={{ backgroundColor: colors.primary }}>
{colors.secondary}
</div>
);
};
MyComponent.propTypes = {
colors: PropTypes.objectOf(PropTypes.string),
};
export default MyComponent;
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({ user }) => {
return (
<div>
{user.name} - {user.age}
</div>
);
};
MyComponent.propTypes = {
user: PropTypes.shape({
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
}),
};
export default MyComponent;
このコードでは、MyComponent
コンポーネントはuser
というプロパティを受け取ります。user
プロパティはオブジェクトであること、そしてその中にname
とage
というプロパティが存在し、それぞれが文字列と数値であることが検証されます。プロパティ名の順序は重要ではありません。
また、React 16.8以降では、prop-types
パッケージではなく、@types/prop-types
パッケージを使用することを推奨されています。
- Using Flow or TypeScript
Flow and TypeScript are static type checking languages that can be used to check the types of props at compile time. This can provide even more rigorous type checking than PropTypes, and can also help to catch errors early in the development process.
// Flow
import React from 'react';
type Props = {
name: string,
age: number,
};
const MyComponent: React.FC<Props> = ({ name, age }) => {
return (
<div>
{name} - {age}
</div>
);
};
// TypeScript
import React from 'react';
interface Props {
name: string;
age: number;
}
const MyComponent: React.FC<Props> = ({ name, age }) => {
return (
<div>
{name} - {age}
</div>
);
};
- Using a custom validation function
You can also write your own custom validation functions to validate props. This can be useful for more complex validation scenarios, or for validating props that are not supported by PropTypes.
import React from 'react';
const validateUser = (user) => {
if (!user.name || !user.age) {
return new Error('Invalid user object');
}
return null;
};
const MyComponent = ({ user }) => {
const error = validateUser(user);
if (error) {
return <div>{error.message}</div>;
}
return (
<div>
{user.name} - {user.age}
</div>
);
};
- Using a third-party library
There are a number of third-party libraries available for validating props in React. These libraries can provide additional features, such as support for custom validation rules and integration with linting tools.
// Using prop-types-validator
import React from 'react';
import PropTypes from 'prop-types-validator';
const MyComponent = ({ user }) => {
const isValidUser = PropTypes.shape({
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
})(user);
if (!isValidUser) {
return <div>Invalid user object</div>;
}
return (
<div>
{user.name} - {user.age}
</div>
);
};
The best way to validate props in React will depend on your specific needs and preferences. If you are just starting out, PropTypes is a good option to get started with. If you need more rigorous type checking, Flow or TypeScript can be a good choice. And if you need to validate props in a more complex way, you can write your own custom validation function or use a third-party library.
reactjs react-proptypes