@samitouri / QOS-React-2 / commits / cc3dc21be0

Tweak Forms

Dan Abramov committed Oct 27, 2016 at 02:02 UTC cc3dc21be01bd8f1e4d74d16a0cd795357c0be89
2 files changed +148 -71
docs/docs/forms.md
+147 -70
@@ -9,7 +9,7 @@ redirect_from: "tips/controlled-input-null-value.html"
9
10 Form components such as `<input>`, `<textarea>`, and `<option>` differ from other native components because they can be mutated via user interactions. These components provide interfaces that make it easier to manage forms in response to user interactions.
11
12 -Two types of form components:
12 +There are two types of form components:
13
14 * Controlled Components
15 * Uncontrolled Components
@@ -20,15 +20,19 @@ You can jump directly to <a href="/react/docs/forms.html#examples">examples</a>.
20
21 A **controlled** form component provides a `value` prop. A **controlled** component does not maintain its own internal state; the component renders purely based on props.
22
23 -```javascript
23 +```javascript{5}
24 render() {
25 - return <input type="text" value="Hello!" />;
25 + return (
26 + <input
27 + type="text"
28 + value="Hello!" />
29 + );
30 }
31 ```
32
29 -User input has no effect on the rendered element because React has declared the value to be "Hello!".
33 +If you try to run this example, you will notice that the input doesn't change as you type. This is because the component has declared the input's `value` to always be `"Hello!"`.
34
31 -To update the value in response to user input, you would use the `onChange` event to save the new value, then pass that to the `value` prop of the form:
35 +To update the value in response to user input, you would use the `onChange` event to save the new value, then pass that to the `value` prop of the input:
36
37 ```javascript{10,22,23}
38 class Form extends React.Component {
@@ -54,34 +58,53 @@ class Form extends React.Component {
58 placeholder="Hello!"
59 value={this.state.value}
60 onChange={this.handleChange} />
57 - <button onClick={this.handleSubmit}>Submit</button>
61 + <button onClick={this.handleSubmit}>
62 + Submit
63 + </button>
64 </div>
65 );
66 }
67 }
68
63 -ReactDOM.render(<Form />, document.getElementById('root'));
69 +ReactDOM.render(
70 + <Form />,
71 + document.getElementById('root')
72 +);
73 ```
74
66 -[Try it on CodePen.](https://codepen.io/ericnakagawa/pen/QKkJva?editors=0010)
75 +[Try it on CodePen.](https://codepen.io/gaearon/pen/NRmBmq?editors=0010)
76
77 In this example, we are accepting the value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
78
70 -```javascript
79 +```javascript{3}
80 handleChange(event) {
72 - this.setState({value: event.target.value.substr(0, 140)});
81 + this.setState({
82 + value: event.target.value.substr(0, 140)
83 + });
84 }
85 ```
86
87 This would accept user input and truncate the value to the first 140 characters.
88
89 +Controlled components also let us reset inputs to arbitrary values by setting the state:
90 +
91 +```javascript{3}
92 + handleClearClick() {
93 + this.setState({
94 + value: ''
95 + });
96 + }
97 +```
98 +
99 ### Potential Issues With Checkboxes and Radio Buttons
100
80 -Be aware that, in an attempt to normalize change handling for checkbox and radio inputs, React uses a `click` event in place of a `change` event. For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
101 +Be aware that, in an attempt to normalize change handling for checkbox and radio inputs, React listens to a `click` browser event to implement the `onChange` event.
102 +
103 +For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
104
105 ## Uncontrolled Components
106
84 -Form components that do not provide a `value` prop are *uncontrolled*.
107 +Form components that do not provide a `value` prop are **uncontrolled**.
108
109 The example below renders an `<input>` control with an empty value. Any user input will be immediately reflected by the rendered element.
110
@@ -95,7 +118,7 @@ An **uncontrolled** component manages its own state.
118
119 If you wanted to listen to updates to the value, you could use the `onChange` event just like you can with controlled components. However, you would _not_ pass the value you saved to the component.
120
98 -```javascript{10,22}
121 +```javascript{25}
122 class Form extends React.Component {
123 constructor(props) {
124 super(props);
@@ -105,6 +128,8 @@ class Form extends React.Component {
128 }
129
130 handleChange(event) {
131 + // Note: with uncontrolled inputs, you don't
132 + // have to put the value in the state.
133 this.setState({value: event.target.value});
134 }
135
@@ -115,21 +140,29 @@ class Form extends React.Component {
140 render() {
141 return (
142 <div>
118 - <input type="text"
143 + <input
144 + type="text"
145 placeholder="Hello!"
146 onChange={this.handleChange} />
121 - <button onClick={this.handleSubmit}>Submit</button>
147 + <button onClick={this.handleSubmit}>
148 + Submit
149 + </button>
150 </div>
151 );
152 }
153 }
154
127 -ReactDOM.render(<Form />, document.getElementById('root'));
155 +ReactDOM.render(
156 + <Form />,
157 + document.getElementById('root')
158 +);
159 ```
160
130 -[Try it on CodePen.](https://codepen.io/ericnakagawa/pen/XjxyoL?editors=0010)
161 +[Try it on CodePen.](https://codepen.io/gaearon/pen/pEBOJR?editors=0010)
162 +
163 +While this example puts value in the state so we can later read it in `handleSubmit()`, uncontrolled form components don't require this. You may completely omit an `onChange` handler and instead read the input value using [DOM references](/react/docs/refs-and-the-dom.html), an advanced feature discussed later.
164
132 -###Default Values
165 +### Default Values
166
167 To initialize an uncontrolled component with a non-empty value, you can supply a `defaultValue` prop.
168
@@ -190,7 +223,7 @@ Since this method describes the view at any point in time, the value of the text
223 In HTML, the value of `<textarea>` is usually set using its children:
224
225 ```html
193 - <!-- antipattern: DO NOT DO THIS! -->
226 + <!-- Don't do this in React. -->
227 <textarea name="description">This is the description.</textarea>
228 ```
229
@@ -220,16 +253,16 @@ To make an uncontrolled component, `defaultValue` is used instead.
253 >
254 > You can pass an array into the `value` attribute, allowing you to select multiple options in a `select` tag: `<select multiple={true} value={['B', 'C']}>`.
255
223 -### Imperative operations
256 +### Imperative Operations
257
258 If you need to imperatively perform an operation, you have to obtain a [reference to the DOM node](/react/docs/more-about-refs.html#the-ref-callback-attribute).
259 For instance, if you want to imperatively submit a form, one approach would be to attach a `ref` to the `form` element and manually call `form.submit()`.
260
261 ## Examples
262
230 -### Basic Controlled Input
263 +### Controlled Input
264
232 -```javascript
265 +```javascript{10,23,24}
266 class Form extends React.Component {
267 constructor(props) {
268 super(props);
@@ -237,6 +270,7 @@ class Form extends React.Component {
270 this.handleChange = this.handleChange.bind(this);
271 this.handleSubmit = this.handleSubmit.bind(this);
272 }
273 +
274 handleChange(event) {
275 this.setState({value: event.target.value});
276 }
@@ -254,21 +288,25 @@ class Form extends React.Component {
288 value={this.state.value}
289 onChange={this.handleChange}
290 />
257 - <button onClick={this.handleSubmit}>Submit</button>
291 + <button onClick={this.handleSubmit}>
292 + Submit
293 + </button>
294 </div>
295 );
296 }
297 }
298
263 -ReactDOM.render(<Form />, document.getElementById('root'));
299 +ReactDOM.render(
300 + <Form />,
301 + document.getElementById('root')
302 +);
303 ```
304
266 -[Try this on CodePen.](https://codepen.io/ericnakagawa/pen/JRmZjz?editors=0010)
267 -
305 +[Try it out on CodePen.](https://codepen.io/gaearon/pen/JRVaYB?editors=0010)
306
269 -### Basic Controlled Textarea
307 +### Controlled Textarea
308
271 -```javascript
309 +```javascript{10,22,23}
310 class Form extends React.Component {
311 constructor(props) {
312 super(props);
@@ -293,20 +331,26 @@ class Form extends React.Component {
331 value={this.state.value}
332 onChange={this.handleChange}
333 />
296 - <button onClick={this.handleSubmit}>Submit</button>
334 + <br />
335 + <button onClick={this.handleSubmit}>
336 + Submit
337 + </button>
338 </div>
339 );
340 }
341 }
342
302 -ReactDOM.render(<Form />, document.getElementById('root'));
343 +ReactDOM.render(
344 + <Form />,
345 + document.getElementById('root')
346 +);
347 ```
348
305 -[Try this on CodePen.](https://codepen.io/ericnakagawa/pen/kkAQPp?editors=0010)
349 +[Try it out on CodePen.](https://codepen.io/gaearon/pen/NRmLxN?editors=0010)
350
307 -### Basic Uncontrolled Select
351 +### Controlled Select
352
309 -```javascript
353 +```javascript{10,20}
354 class Form extends React.Component {
355 constructor(props) {
356 super(props);
@@ -331,20 +375,25 @@ class Form extends React.Component {
375 <option value="B">Banana</option>
376 <option value="C">Cranberry</option>
377 </select>
334 - <button onClick={this.handleSubmit}>Submit</button>
378 + <button onClick={this.handleSubmit}>
379 + Submit
380 + </button>
381 </div>
382 );
383 }
384 }
385
340 -ReactDOM.render(<Form />, document.getElementById('root'));
386 +ReactDOM.render(
387 + <Form />,
388 + document.getElementById('root')
389 +);
390 ```
391
343 -[Try this on CodePen.](https://codepen.io/ericnakagawa/pen/pExQbL?editors=0010)
392 +[Try it out on CodePen.](https://codepen.io/gaearon/pen/qawrbr?editors=0010)
393
345 -### Basic Radio Button
394 +### Uncontrolled Radio Button
395
347 -```javascript
396 +```javascript{25,34,35,44}
397 class Form extends React.Component {
398 constructor(props) {
399 super(props);
@@ -365,38 +414,53 @@ class Form extends React.Component {
414 return (
415 <div>
416 <label>
368 - <input type="radio" value="A" id="choice-a"
417 + <input
418 + type="radio"
419 + name="choice"
420 + value="A"
421 onChange={this.handleChange} />
422 Option A
423 </label>
424 <br />
425 <label>
374 - <input type="radio" value="B" id="choice-b"
375 - onChange={this.handleChange} defaultChecked={true} />
426 + <input
427 + type="radio"
428 + name="choice"
429 + value="B"
430 + onChange={this.handleChange}
431 + defaultChecked={true} />
432 Option B
433 </label>
434 <br />
435 <label>
380 - <input type="radio" value="C" id="choice-c"
381 - onChange={this.handleChange} />
436 + <input
437 + type="radio"
438 + name="choice"
439 + value="C"
440 + onChange={this.handleChange} />
441 Option C
442 </label>
384 - <br /><br />
385 - <button onClick={this.handleSubmit}>Submit</button>
443 + <br />
444 + <br />
445 + <button onClick={this.handleSubmit}>
446 + Submit
447 + </button>
448 </div>
449 );
450 }
451 }
452
391 -ReactDOM.render(<Form />, document.getElementById('root'));
453 +ReactDOM.render(
454 + <Form />,
455 + document.getElementById('root')
456 +);
457 ```
458
394 -[Try this on CodePen.](https://codepen.io/ericnakagawa/pen/WGaYVg?editors=0010)
459 +[Try it out on CodePen.](https://codepen.io/gaearon/pen/ozOPLJ?editors=0010)
460
461 +### Uncontrolled Checkbox
462
397 -### Basic Uncontrolled Checkbox
398 -
399 -```javascript
463 +```javascript{37,45,46,54}
464 class Form extends React.Component {
465 constructor(props) {
466 super(props);
@@ -406,10 +470,16 @@ class Form extends React.Component {
470 }
471
472 handleChange(event) {
409 - let value = event.target.value;
410 - let checked = this.state.checked; // copy
411 - if (!checked[value]) { checked[value] = true; } else { checked[value] = false; }
412 - this.setState({checked: checked})
473 + const value = event.target.value;
474 + // Copy the object so we don't mutate the old state.
475 + // (This requires an Object.assign polyfill):
476 + const checked = Object.assign({}, this.state.checked)
477 + if (!checked[value]) {
478 + checked[value] = true;
479 + } else {
480 + checked[value] = false;
481 + };
482 + this.setState({checked});
483 }
484
485 handleSubmit(event) {
@@ -424,36 +494,43 @@ class Form extends React.Component {
494 return (
495 <div>
496 <label>
427 - <input type="checkbox" value="A"
497 + <input
498 + type="checkbox"
499 + value="A"
500 onChange={this.handleChange} />
501 Option A
502 </label>
503 <br />
504 <label>
433 - <input type="checkbox" value="B"
434 - onChange={this.handleChange} defaultChecked={true} />
505 + <input
506 + type="checkbox"
507 + value="B"
508 + onChange={this.handleChange}
509 + defaultChecked={true} />
510 Option B
511 </label>
512 <br />
438 - <label><input type="checkbox" value="C"
513 + <label>
514 + <input
515 + type="checkbox"
516 + value="C"
517 onChange={this.handleChange} />
518 Option C
519 </label>
442 - <br /><br />
443 - <button onClick={this.handleSubmit}>Submit</button>
520 + <br />
521 + <br />
522 + <button onClick={this.handleSubmit}>
523 + Submit
524 + </button>
525 </div>
526 );
527 }
528 }
448 -ReactDOM.render(<Form />, document.getElementById('root'));
449 -```
450 -
451 -[Try it on CodePen.](https://codepen.io/ericnakagawa/pen/kkAzPO?editors=0010)
452 -
453 -### Form Events
454 -
455 -Event names:
529
530 +ReactDOM.render(
531 + <Form />,
532 + document.getElementById('root')
533 +);
534 ```
458 -onChange onInput onSubmit
459 -```
535 +
536 +[Try it on CodePen.](https://codepen.io/gaearon/pen/rrbkWz?editors=0010)
docs/docs/reference-events.md
+1 -1
@@ -35,7 +35,7 @@ string type
35 >
36 > As of v0.14, returning `false` from an event handler will no longer stop event propagation. Instead, `e.stopPropagation()` or `e.preventDefault()` should be triggered manually, as appropriate.
37
38 -### Event pooling
38 +### Event Pooling
39
40 The `SyntheticEvent` is pooled. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event callback has been invoked.
41 This is for performance reasons.