When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc.) into reusable components with well-defined interfaces. That way, the next time you need to build some UI, you can write much less code. This means faster development time, fewer bugs, and fewer bytes down the wire.
Prop Validation
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify propTypes
. React.PropTypes
exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons propTypes
is only checked in development mode. Here is an example documenting the different validators provided:
React.createClass({ propTypes: { // You can declare that a prop is a specific JS primitive. By default, these // are all optional. optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, // Anything that can be rendered: numbers, strings, elements or an array // (or fragment) containing these types. optionalNode: React.PropTypes.node, // A React element. optionalElement: React.PropTypes.element, // You can also declare that a prop is an instance of a class. This uses // JS's instanceof operator. optionalMessage: React.PropTypes.instanceOf(Message), // You can ensure that your prop is limited to specific values by treating // it as an enum. optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // An object that could be one of many types optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // An array of a certain type optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // An object with property values of a certain type optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // An object taking on a particular shape optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // You can chain any of the above with `isRequired` to make sure a warning // is shown if the prop isn't provided. requiredFunc: React.PropTypes.func.isRequired, // A value of any data type requiredAny: React.PropTypes.any.isRequired, // You can also specify a custom validator. It should return an Error // object if the validation fails. Don't `console.warn` or throw, as this // won't work inside `oneOfType`. customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error( 'Invalid prop `' + propName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }, // You can also supply a custom validator to `arrayOf` and `objectOf`. // It should return an Error object if the validation fails. The validator // will be called for each key in the array or object. The first two // arguments of the validator are the array or object itself, and the // current item's key. customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { if (!/matchme/.test(propValue[key])) { return new Error( 'Invalid prop `' + propFullName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }) }, /* ... */ });
Single Child
With React.PropTypes.element
you can specify that only a single child can be passed to a component as children.
var MyComponent = React.createClass({ propTypes: { children: React.PropTypes.element.isRequired }, render: function() { return ( <div> {this.props.children} // This must be exactly one element or it will warn. </div> ); } });
Default Prop Values
React lets you define default values for your props
in a very declarative way:
var ComponentWithDefaultProps = React.createClass({ getDefaultProps: function() { return { value: 'default value' }; } /* ... */ });
The result of getDefaultProps()
will be cached and used to ensure that this.props.value
will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
Transferring Props: A Shortcut
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX spread syntax to achieve this:
var CheckLink = React.createClass({ render: function() { // This takes any props passed to CheckLink and copies them to <a> return <a {...this.props}>{'√ '}{this.props.children}</a>; } }); ReactDOM.render( <CheckLink href="/checked.html"> Click here! </CheckLink>, document.getElementById('example') );
Mixins
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called cross-cutting concerns. React provides mixins
to solve this problem.
One common use case is a component wanting to update itself on a time interval. It's easy to use setInterval()
, but it's important to cancel your interval when you don't need it anymore to save memory. React provides lifecycle methods that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy setInterval()
function that will automatically get cleaned up when your component is destroyed.
var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.forEach(clearInterval); } }; var TickTock = React.createClass({ mixins: [SetIntervalMixin], // Use the mixin getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { this.setInterval(this.tick, 1000); // Call a method on the mixin }, tick: function() { this.setState({seconds: this.state.seconds + 1}); }, render: function() { return ( <p> React has been running for {this.state.seconds} seconds. </p> ); } }); ReactDOM.render( <TickTock />, document.getElementById('example') );
A nice feature of mixins is that if a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
ES6 Classes
You may also define your React classes as a plain JavaScript class. For example using ES6 class syntax:
class HelloMessage extends React.Component { render() { return <div>Hello {this.props.name}</div>; } } ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
The API is similar to React.createClass
with the exception of getInitialState
. Instead of providing a separate getInitialState
method, you set up your own state
property in the constructor.
Another difference is that propTypes
and defaultProps
are defined as properties on the constructor instead of in the class body.
export class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; this.tick = this.tick.bind(this); } tick() { this.setState({count: this.state.count + 1}); } render() { return ( <div onClick={this.tick}> Clicks: {this.state.count} </div> ); } } Counter.propTypes = { initialCount: React.PropTypes.number }; Counter.defaultProps = { initialCount: 0 };
No Autobinding
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind this
to the instance. You'll have to explicitly use .bind(this)
or arrow functions =>
:
// You can use bind() to preserve `this` <div onClick={this.tick.bind(this)}> // Or you can use arrow functions <div onClick={() => this.tick()}>
We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:
constructor(props) { super(props); this.state = {count: props.initialCount}; this.tick = this.tick.bind(this); }
Now you can use this.tick
directly as it was bound once in the constructor:
// It is already bound in the constructor <div onClick={this.tick}>
This is better for performance of your application, especially if you implement shouldComponentUpdate() with a shallow comparison in the child components.
No Mixins
Unfortunately ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. Instead, we're working on making it easier to support such use cases without resorting to mixins.
Stateless Functions
You may also define your React classes as a plain JavaScript function. For example using the stateless function syntax:
function HelloMessage(props) { return <div>Hello {props.name}</div>; } ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
Or using the new ES6 arrow syntax:
const HelloMessage = (props) => <div>Hello {props.name}</div>; ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate. However, you may still specify .propTypes
and .defaultProps
by setting them as properties on the function, just as you would set them on an ES6 class.
NOTE:
Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
NOTE:
In React v0.14, stateless functional components were not permitted to return
null
orfalse
(a workaround is to return a<noscript />
instead). This was fixed in React v15, and stateless functional components are now permitted to returnnull
.
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.
Please login to continue.