OSDN Git Service

Regular updates
[twpd/master.git] / react.md
1 ---
2 title: React.js
3 category: React
4 layout: 2017/sheet
5 ads: true
6 tags: [Featured]
7 updated: 2018-10-04
8 weight: -10
9 keywords:
10   - React.Component
11   - render()
12   - componentDidMount()
13   - props/state
14   - dangerouslySetInnerHTML
15 intro: |
16   [React](https://reactjs.org/) is a JavaScript library for building user interfaces. This guide targets React v15 to v16.
17 ---
18
19 {%raw%}
20
21 Components
22 ----------
23 {: .-three-column}
24
25 ### Components
26 {: .-prime}
27
28 ```jsx
29 import React from 'react'
30 import ReactDOM from 'react-dom'
31 ```
32 {: .-setup}
33
34 ```jsx
35 class Hello extends React.Component {
36   render () {
37     return <div className='message-box'>
38       Hello {this.props.name}
39     </div>
40   }
41 }
42 ```
43
44 ```jsx
45 const el = document.body
46 ReactDOM.render(<Hello name='John' />, el)
47 ```
48
49 Use the [React.js jsfiddle](http://jsfiddle.net/reactjs/69z2wepo/) to start hacking. (or the unofficial [jsbin](http://jsbin.com/yafixat/edit?js,output))
50
51 ### Import multiple exports
52 {: .-prime}
53
54 ```jsx
55 import React, {Component} from 'react'
56 import ReactDOM from 'react-dom'
57 ```
58 {: .-setup}
59
60 ```jsx
61 class Hello extends Component {
62   ...
63 }
64 ```
65
66 ### Properties
67
68 ```html
69 <Video fullscreen={true} autoplay={false} />
70 ```
71 {: .-setup}
72
73 ```jsx
74 render () {
75   this.props.fullscreen
76   const { fullscreen, autoplay } = this.props
77   ···
78 }
79 ```
80 {: data-line="2,3"}
81
82 Use `this.props` to access properties passed to the component.
83
84 See: [Properties](https://reactjs.org/docs/tutorial.html#using-props)
85
86 ### States
87
88 ```jsx
89 constructor(props) {
90   super(props)
91   this.state = { username: undefined }
92 }
93 ```
94
95 ```jsx
96 this.setState({ username: 'rstacruz' })
97 ```
98
99 ```jsx
100 render () {
101   this.state.username
102   const { username } = this.state
103   ···
104 }
105 ```
106 {: data-line="2,3"}
107
108 Use states (`this.state`) to manage dynamic data.
109
110 With [Babel](https://babeljs.io/) you can use [proposal-class-fields](https://github.com/tc39/proposal-class-fields) and get rid of constructor
111
112 ```jsx
113 class Hello extends Component {
114   state = { username: undefined };
115   ...
116 }
117 ```
118
119 See: [States](https://reactjs.org/docs/tutorial.html#reactive-state)
120
121
122 ### Nesting
123
124 ```jsx
125 class Info extends Component {
126   render () {
127     const { avatar, username } = this.props
128
129     return <div>
130       <UserAvatar src={avatar} />
131       <UserProfile username={username} />
132     </div>
133   }
134 }
135 ```
136 As of React v16.2.0, fragments can be used to return multiple children without adding extra wrapping nodes to the DOM.
137
138 ```jsx
139 import React, {
140   Component,
141   Fragment
142 } from 'react'
143
144 class Info extends Component {
145   render () {
146     const { avatar, username } = this.props
147
148     return (
149       <Fragment>
150         <UserAvatar src={avatar} />
151         <UserProfile username={username} />
152       </Fragment>
153     )
154   }
155 }
156 ```
157
158 {: data-line="5,6,7,8,9,10"}
159
160 Nest components to separate concerns.
161
162 See: [Composing Components](https://reactjs.org/docs/components-and-props.html#composing-components)
163
164 ### Children
165
166 ```jsx
167 <AlertBox>
168   <h1>You have pending notifications</h1>
169 </AlertBox>
170 ```
171 {: data-line="2"}
172
173 ```jsx
174 class AlertBox extends Component {
175   render () {
176     return <div className='alert-box'>
177       {this.props.children}
178     </div>
179   }
180 }
181 ```
182 {: data-line="4"}
183
184 Children are passed as the `children` property.
185
186 Defaults
187 --------
188
189 ### Setting default props
190
191 ```jsx
192 Hello.defaultProps = {
193   color: 'blue'
194 }
195 ```
196 {: data-line="1"}
197
198 See: [defaultProps](https://reactjs.org/docs/react-component.html#defaultprops)
199
200 ### Setting default state
201
202 ```jsx
203 class Hello extends Component {
204   constructor (props) {
205     super(props)
206     this.state = { visible: true }
207   }
208 }
209 ```
210 {: data-line="4"}
211
212 Set the default state in the `constructor()`.
213
214 And without constructor using [Babel](https://babeljs.io/) with [proposal-class-fields](https://github.com/tc39/proposal-class-fields).
215
216 ```jsx
217 class Hello extends Component {
218     state = { visible: true }
219   }
220 }
221 ```
222 {: data-line="2"}
223
224 See: [Setting the default state](https://reactjs.org/docs/react-without-es6.html#setting-the-initial-state)
225
226 Other components
227 ----------------
228 {: .-three-column}
229
230 ### Functional components
231
232 ```jsx
233 function MyComponent ({ name }) {
234   return <div className='message-box'>
235     Hello {name}
236   </div>
237 }
238 ```
239 {: data-line="1"}
240
241 Functional components have no state. Also, their `props` are passed as the first parameter to a function.
242
243 See: [Function and Class Components](https://reactjs.org/docs/components-and-props.html#functional-and-class-components)
244
245 ### Pure components
246
247 ```jsx
248 import React, {PureComponent} from 'react'
249
250 class MessageBox extends PureComponent {
251   ···
252 }
253 ```
254 {: data-line="3"}
255
256 Performance-optimized version of `React.Component`. Doesn't rerender if props/state hasn't changed.
257
258 See: [Pure components](https://reactjs.org/docs/react-api.html#react.purecomponent)
259
260 ### Component API
261
262 ```jsx
263 this.forceUpdate()
264 ```
265
266 ```jsx
267 this.setState({ ... })
268 this.setState(state => { ... })
269 ```
270
271 ```jsx
272 this.state
273 this.props
274 ```
275
276 These methods and properties are available for `Component` instances.
277
278 See: [Component API](http://facebook.github.io/react/docs/component-api.html)
279
280 Lifecycle
281 ---------
282 {: .-two-column}
283
284 ### Mounting
285
286 | Method | Description |
287 | --- | --- |
288 | `constructor` _(props)_ | Before rendering [#](https://reactjs.org/docs/react-component.html#constructor) |
289 | `componentWillMount()` | _Don't use this_ [#](https://reactjs.org/docs/react-component.html#componentwillmount) |
290 | `render()` | Render  [#](https://reactjs.org/docs/react-component.html#render) |
291 | `componentDidMount()` | After rendering (DOM available) [#](https://reactjs.org/docs/react-component.html#componentdidmount) |
292 | --- | --- |
293 | `componentWillUnmount()` | Before DOM removal [#](https://reactjs.org/docs/react-component.html#componentwillunmount) |
294 | --- | --- |
295 | `componentDidCatch()` | Catch errors (16+) [#](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) |
296
297 Set initial the state on `constructor()`.
298 Add DOM event handlers, timers (etc) on `componentDidMount()`, then remove them on `componentWillUnmount()`.
299
300 ### Updating
301
302 | Method | Description |
303 | --- | --- |
304 | `componentDidUpdate` *(prevProps, prevState, snapshot)* | Use `setState()` here, but remember to compare props |
305 | `shouldComponentUpdate` *(newProps, newState)* | Skips `render()` if returns false |
306 | `render()` | Render |
307 | `componentDidUpdate` *(prevProps, prevState)* | Operate on the DOM here |
308
309 Called when parents change properties and `.setState()`. These are not called for initial renders.
310
311 See: [Component specs](http://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops)
312
313 Hooks (New)
314 -----------
315 {: .-two-column}
316
317 ### State Hook
318
319 ```jsx
320 import React, { useState } from 'react';
321
322 function Example() {
323   // Declare a new state variable, which we'll call "count"
324   const [count, setCount] = useState(0);
325
326   return (
327     <div>
328       <p>You clicked {count} times</p>
329       <button onClick={() => setCount(count + 1)}>
330         Click me
331       </button>
332     </div>
333   );
334 }
335 ```
336 {: data-line="5,10"}
337
338 Hooks are a new addition in React 16.8.
339
340 See: [Hooks at a Glance](https://reactjs.org/docs/hooks-overview.html)
341
342 ### Declaring multiple state variables
343
344 ```jsx
345 function ExampleWithManyStates() {
346   // Declare multiple state variables!
347   const [age, setAge] = useState(42);
348   const [fruit, setFruit] = useState('banana');
349   const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
350   // ...
351 }
352 ```
353
354 ### Effect hook
355
356 ```jsx
357 import React, { useState, useEffect } from 'react';
358
359 function Example() {
360   const [count, setCount] = useState(0);
361
362   // Similar to componentDidMount and componentDidUpdate:
363   useEffect(() => {
364     // Update the document title using the browser API
365     document.title = `You clicked ${count} times`;
366   }, [count]);
367
368   return (
369     <div>
370       <p>You clicked {count} times</p>
371       <button onClick={() => setCount(count + 1)}>
372         Click me
373       </button>
374     </div>
375   );
376 }
377 ```
378 {: data-line="6,7,8,9,10"}
379
380 If you’re familiar with React class lifecycle methods, you can think of `useEffect` Hook as `componentDidMount`, `componentDidUpdate`, and `componentWillUnmount` combined.
381
382 By default, React runs the effects after every render — including the first render.
383
384 ### Building your own hooks
385
386 #### Define FriendStatus
387 ```jsx
388 import React, { useState, useEffect } from 'react';
389
390 function FriendStatus(props) {
391   const [isOnline, setIsOnline] = useState(null);
392
393   useEffect(() => {
394     function handleStatusChange(status) {
395       setIsOnline(status.isOnline);
396     }
397
398     ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
399     return () => {
400       ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
401     };
402   }, [props.friend.id]);
403
404   if (isOnline === null) {
405     return 'Loading...';
406   }
407   return isOnline ? 'Online' : 'Offline';
408 }
409 ```
410 {: data-line="11,12,13,14"}
411
412 Effects may also optionally specify how to “clean up” after them by returning a function. 
413
414 #### Use FriendStatus
415
416 ```jsx
417 function FriendStatus(props) {
418   const isOnline = useFriendStatus(props.friend.id);
419
420   if (isOnline === null) {
421     return 'Loading...';
422   }
423   return isOnline ? 'Online' : 'Offline';
424 }
425 ```
426 {: data-line="2"}
427
428 See: [Building Your Own Hooks](https://reactjs.org/docs/hooks-custom.html)
429
430 ### Hooks API Reference
431
432 Also see: [Hooks FAQ](https://reactjs.org/docs/hooks-faq.html)
433
434 #### Basic Hooks
435
436 | Hook                         | Description                               |
437 | ---------------------------- | ----------------------------------------- |
438 | `useState`_(initialState)_   |                                           |
439 | `useEffect`_(() => { ... })_ |                                           |
440 | `useContext`_(MyContext)_    | value returned from `React.createContext` |
441
442 Full details: [Basic Hooks](https://reactjs.org/docs/hooks-reference.html#basic-hooks)
443
444 #### Additional Hooks
445
446 | Hook                                         | Description                                                                 |
447 | -------------------------------------------- | ---------------------------------------------------------------------------- |
448 | `useReducer`_(reducer, initialArg, init)_    |                                                                              |
449 | `useCallback`_(() => { ... })_               |                                                                              |
450 | `useMemo`_(() => { ... })_                   |                                                                              |
451 | `useRef`_(initialValue)_                     |                                                                              |
452 | `useImperativeHandle`_(ref, () => { ... })_  |                                                                              |
453 | `useLayoutEffect`                            | identical to `useEffect`, but it fires synchronously after all DOM mutations |
454 | `useDebugValue`_(value)_                     | display a label for custom hooks in React DevTools                           |
455
456 Full details: [Additional Hooks](https://reactjs.org/docs/hooks-reference.html#additional-hooks)
457
458 DOM nodes
459 ---------
460 {: .-two-column}
461
462 ### References
463
464 ```jsx
465 class MyComponent extends Component {
466   render () {
467     return <div>
468       <input ref={el => this.input = el} />
469     </div>
470   }
471
472   componentDidMount () {
473     this.input.focus()
474   }
475 }
476 ```
477 {: data-line="4,9"}
478
479 Allows access to DOM nodes.
480
481 See: [Refs and the DOM](https://reactjs.org/docs/refs-and-the-dom.html)
482
483 ### DOM Events
484
485 ```jsx
486 class MyComponent extends Component {
487   render () {
488     <input type="text"
489         value={this.state.value}
490         onChange={event => this.onChange(event)} />
491   }
492
493   onChange (event) {
494     this.setState({ value: event.target.value })
495   }
496 }
497 ```
498 {: data-line="5,9"}
499
500 Pass functions to attributes like `onChange`.
501
502 See: [Events](https://reactjs.org/docs/events.html)
503
504 ## Other features
505
506 ### Transferring props
507
508 ```html
509 <VideoPlayer src="video.mp4" />
510 ```
511 {: .-setup}
512
513 ```jsx
514 class VideoPlayer extends Component {
515   render () {
516     return <VideoEmbed {...this.props} />
517   }
518 }
519 ```
520 {: data-line="3"}
521
522 Propagates `src="..."` down to the sub-component.
523
524 See [Transferring props](http://facebook.github.io/react/docs/transferring-props.html)
525
526 ### Top-level API
527
528 ```jsx
529 React.createClass({ ... })
530 React.isValidElement(c)
531 ```
532
533 ```jsx
534 ReactDOM.render(<Component />, domnode, [callback])
535 ReactDOM.unmountComponentAtNode(domnode)
536 ```
537
538 ```jsx
539 ReactDOMServer.renderToString(<Component />)
540 ReactDOMServer.renderToStaticMarkup(<Component />)
541 ```
542
543 There are more, but these are most common.
544
545 See: [React top-level API](https://reactjs.org/docs/react-api.html)
546
547 JSX patterns
548 ------------
549 {: .-two-column}
550
551 ### Style shorthand
552
553 ```jsx
554 const style = { height: 10 }
555 return <div style={style}></div>
556 ```
557
558 ```jsx
559 return <div style={{ margin: 0, padding: 0 }}></div>
560 ```
561
562 See: [Inline styles](https://reactjs.org/tips/inline-styles.html)
563
564 ### Inner HTML
565
566 ```jsx
567 function markdownify() { return "<p>...</p>"; }
568 <div dangerouslySetInnerHTML={{__html: markdownify()}} />
569 ```
570
571 See: [Dangerously set innerHTML](https://reactjs.org/tips/dangerously-set-inner-html.html)
572
573 ### Lists
574
575 ```jsx
576 class TodoList extends Component {
577   render () {
578     const { items } = this.props
579
580     return <ul>
581       {items.map(item =>
582         <TodoItem item={item} key={item.key} />)}
583     </ul>
584   }
585 }
586 ```
587 {: data-line="6,7"}
588
589 Always supply a `key` property.
590
591 ### Conditionals
592
593 ```jsx
594 <Fragment>
595   {showMyComponent
596     ? <MyComponent />
597     : <OtherComponent />}
598 </Fragment>
599 ```
600
601 ### Short-circuit evaluation
602
603 ```jsx
604 <Fragment>
605   {showPopup && <Popup />}
606   ...
607 </Fragment>
608 ```
609
610 New features
611 ------------
612 {: .-three-column}
613
614 ### Returning multiple elements
615
616 You can return multiple elements as arrays or fragments.
617
618 #### Arrays
619
620 ```js
621 render () {
622   // Don't forget the keys!
623   return [
624     <li key="A">First item</li>,
625     <li key="B">Second item</li>
626   ]
627 }
628 ```
629 {: data-line="3,4,5,6"}
630
631 #### Fragments
632 ```js
633 render () {
634   // Fragments don't require keys!
635   return (
636     <Fragment>
637       <li>First item</li>
638       <li>Second item</li>
639     </Fragment>
640   )
641 }
642 ```
643 {: data-line="3,4,5,6,7,8"}
644
645 See: [Fragments and strings](https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings)
646
647 ### Returning strings
648
649 ```js
650 render() {
651   return 'Look ma, no spans!';
652 }
653 ```
654 {: data-line="2"}
655
656 You can return just a string.
657
658 See: [Fragments and strings](https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings)
659
660 ### Errors
661
662 ```js
663 class MyComponent extends Component {
664   ···
665   componentDidCatch (error, info) {
666     this.setState({ error })
667   }
668 }
669 ```
670 {: data-line="3,4,5"}
671
672 Catch errors via `componentDidCatch`. (React 16+)
673
674 See: [Error handling in React 16](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html)
675
676 ### Portals
677
678 ```js
679 render () {
680   return React.createPortal(
681     this.props.children,
682     document.getElementById('menu')
683   )
684 }
685 ```
686 {: data-line="2,3,4,5"}
687
688 This renders `this.props.children` into any location in the DOM.
689
690 See: [Portals](https://reactjs.org/docs/portals.html)
691
692 ### Hydration
693
694 ```js
695 const el = document.getElementById('app')
696 ReactDOM.hydrate(<App />, el)
697 ```
698 {: data-line="2"}
699
700 Use `ReactDOM.hydrate` instead of using `ReactDOM.render` if you're rendering over the output of [ReactDOMServer](https://reactjs.org/docs/react-dom-server.html).
701
702 See: [Hydrate](https://reactjs.org/docs/react-dom.html#hydrate)
703
704 Property validation
705 -------------------
706 {: .-three-column}
707
708 ### PropTypes
709
710 ```js
711 import PropTypes from 'prop-types'
712 ```
713 {: .-setup}
714
715 See: [Typechecking with PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html)
716
717 | `any`                     | Anything                             |
718
719 #### Basic
720
721 | `string`                  |                                      |
722 | `number`                  |                                      |
723 | `func`                    | Function                             |
724 | `bool`                    | True or false                        |
725
726 #### Enum
727
728 | `oneOf`_(any)_            | Enum types                           |
729 | `oneOfType`_(type array)_ | Union                                |
730
731 #### Array
732
733 | `array`                   |                                      |
734 | `arrayOf`_(...)_          |                                      |
735
736 #### Object
737
738 | `object`                  |                                      |
739 | `objectOf`_(...)_         | Object with values of a certain type |
740 | `instanceOf`_(...)_       | Instance of a class                  |
741 | `shape`_(...)_            |                                      |
742
743 #### Elements
744
745 | `element`                 | React element                        |
746 | `node`                    | DOM node                             |
747
748 #### Required
749
750 | `(···).isRequired`        | Required                             |
751
752 ### Basic types
753
754 ```jsx
755 MyComponent.propTypes = {
756   email:      PropTypes.string,
757   seats:      PropTypes.number,
758   callback:   PropTypes.func,
759   isClosed:   PropTypes.bool,
760   any:        PropTypes.any
761 }
762 ```
763
764 ### Required types
765
766 ```jsx
767 MyCo.propTypes = {
768   name:  PropTypes.string.isRequired
769 }
770 ```
771
772 ### Elements
773
774 ```jsx
775 MyCo.propTypes = {
776   // React element
777   element: PropTypes.element,
778
779   // num, string, element, or an array of those
780   node: PropTypes.node
781 }
782 ```
783
784 ### Enumerables (oneOf)
785
786 ```jsx
787 MyCo.propTypes = {
788   direction: PropTypes.oneOf([
789     'left', 'right'
790   ])
791 }
792 ```
793
794 ### Arrays and objects
795
796 ```jsx
797 MyCo.propTypes = {
798   list: PropTypes.array,
799   ages: PropTypes.arrayOf(PropTypes.number),
800   user: PropTypes.object,
801   user: PropTypes.objectOf(PropTypes.number),
802   message: PropTypes.instanceOf(Message)
803 }
804 ```
805
806 ```jsx
807 MyCo.propTypes = {
808   user: PropTypes.shape({
809     name: PropTypes.string,
810     age:  PropTypes.number
811   })
812 }
813 ```
814
815 Use `.array[Of]`, `.object[Of]`, `.instanceOf`, `.shape`.
816
817 ### Custom validation
818
819 ```jsx
820 MyCo.propTypes = {
821   customProp: (props, key, componentName) => {
822     if (!/matchme/.test(props[key])) {
823       return new Error('Validation failed!')
824     }
825   }
826 }
827 ```
828
829 Also see
830 --------
831
832 * [React website](https://reactjs.org) _(reactjs.org)_
833 * [React cheatsheet](https://reactcheatsheet.com/) _(reactcheatsheet.com)_
834 * [Awesome React](https://github.com/enaqx/awesome-react) _(github.com)_
835 * [React v0.14 cheatsheet](react@0.14) _Legacy version_
836
837 {%endraw%}