22
33In this sample we are going to refactor the previous sample ** 03 State** .
44
5- We'll update the name property only when the user clicks on
6- a _ change_ button, we will simplify the event itself as well.
5+ We'll update the name property only when the user clicks on a _ change_ button, we will simplify the event itself as well.
76
8- Obviously, we will take the sample ** 03 State** as a starting point.
7+ Obviously, we will take the sample _ [ 03 State] ( ../03%20State/ ) _ as a starting point.
98
109Summary steps:
1110
@@ -21,101 +20,130 @@ Install [Node.js and npm](https://nodejs.org/en/) (v6.6.0 or newer) if they are
2120
2221## Steps to build it
2322
24- - Copy the content of the ` 03 State ` folder to an empty folder for the sample
25- and make this your current folder.
23+ - Copy the content of the _ [ 03 State] ( ../03%20State/ ) _ folder to an empty folder for the sample and make this your current folder.
2624
2725- Install the npm packages described in the ` package.json ` and verify that it works:
2826
2927 ``` bash
3028 npm install
3129 ```
3230
33- - Since we are going to use an internal handler, we'll transform the ` NameEditComponent `
34- from a stateless component into a class component, then we will add some refactor on the naming.
35-
36- The ` nameEdit.jsx ` file should looks like this:
37-
38- ``` jsx
39- import * as React from ' react' ;
40-
41- export class NameEditComponent extends React .Component {
42-
43- constructor (props ) {
44- super (props);
45- // Watch out what would happen if we get this user name via an AJAX callback
46- // you will find a different implementatin on 05 sample
47- this .state = {
48- editingName: this .props .initialUserName ,
49- };
50-
51- this .onChange = this .onChange .bind (this );
52- this .onNameSubmit = this .onNameSubmit .bind (this );
53- }
54-
55- onChange (event ) {
56- this .setState ({ editingName: event .target .value });
57- }
58-
59- onNameSubmit () {
60- this .props .onNameUpdated (this .state .editingName );
61- }
62-
63- render () {
64- return (
65- < div>
66- < label htmlFor= " editingName" > Update Name: < / label>
67- < input value= {this .state .editingName } onChange= {this .onChange } id= " editingName" / >
68- < input type= " submit" value= " Change" className= " btn btn-default" onClick= {this .onNameSubmit } / >
69- < / div>
70- );
71- }
31+ - Since we are going to use an internal handler, we'll transform the ` NameEditComponent ` from a stateless component into a class component, then we will add some refactor on the naming.
32+
33+ The [ nameEdit.jsx] ( ./src/nameEdit.jsx ) file should looks like this:
34+
35+ _ [ nameEdit.jsx] ( ./src/nameEdit.jsx ) _
36+ ``` diff
37+ import React from 'react';
38+ import PropTypes from 'prop-types';
39+
40+ - - export const NameEditComponent = (props) => (
41+ - - <div>
42+ - - <label htmlFor="userName">Update Name:</label>
43+ - - <input id="userName" value={props.userName} onChange={props.onChange} />
44+ - - </div>
45+ - - );
46+
47+ + + export class NameEditComponent extends React.Component {
48+ + + constructor(props) {
49+ + + super(props);
50+ + + // Watch out what would happen if we get this user name via an AJAX callback
51+ + + // you will find a different implementatin on 05 sample
52+ + + this.state = {
53+ + + editingName: this.props.initialUserName,
54+ + + };
55+
56+ + + this.onChange = this.onChange.bind(this);
57+ + + this.onNameSubmit = this.onNameSubmit.bind(this);
58+ + + }
59+
60+ + + onChange(event) {
61+ + + this.setState({ editingName: event.target.value });
62+ + + }
63+
64+ + + onNameSubmit() {
65+ + + this.props.onNameUpdated(this.state.editingName);
66+ + + }
67+
68+ + + render() {
69+ + + return (
70+ + + <div>
71+ + + <label htmlFor="editingName">Update Name:</label>
72+ + + <input value={this.state.editingName} onChange={this.onChange} id="editingName" />
73+ + + <input type="submit" value="Change" className="btn btn-default" onClick={this.onNameSubmit} />
74+ + + </div>
75+ + + );
76+ + + }
77+ + + }
78+
79+ NameEditComponent.propTypes = {
80+ initialUserName: PropTypes.string.isRequired,
81+ - - onChange: PropTypes.func.isRequired,
82+ + + onNameUpdated: PropTypes.func,
83+ };
84+ ```
85+
86+ - Let's wire this up in the [ app.jsx] ( ./src/app.jsx ) file.
87+
88+ _ [ app.jsx] ( ./src/app.jsx ) _
89+ ``` diff
90+ import React from 'react';
91+ import { HelloComponent } from './hello';
92+ import { NameEditComponent } from './nameEdit';
93+
94+ export class App extends React.Component {
95+ constructor(props) {
96+ super(props);
97+ this.state = {
98+ userName: 'defaultUserName',
99+ };
100+ this.setUsernameState = this.setUsernameState.bind(this);
72101 }
73-
74- NameEditComponent .propTypes = {
75- initialUserName: React .PropTypes .string .isRequired ,
76- onNameUpdated: React .PropTypes .func ,
77- };
78- ```
79-
80- - Let's wire this up in the ` app.jsx ` file.
81-
82- ``` jsx
83- export class App extends React .Component {
84- constructor (props ) {
85- super (props);
86- this .state = { userName: ' defaultUserName' };
87- this .setUsernameState = this .setUsernameState .bind (this );
88- }
89-
90- setUsernameState (newName ) {
91- this .setState ({ userName: newName });
92- }
93-
94- render () {
95- return (
96- < div>
97- < HelloComponent userName= {this .state .userName } / >
98- < NameEditComponent
99- initialUserName= " Javier Cansado"
100- onNameUpdated= {this .setUsernameState }
101- / >
102- < / div>
103- );
104- }
102+ - - setUsernameState(event) {
103+ + + setUsernameState(newName) {
104+ this.setState({
105+ - - userName: event.target.value,
106+ + + userName: newName
107+ });
105108 }
106109
107- ```
110+ render() {
111+ return (
112+ <div>
113+ <HelloComponent userName={this.state.userName} />
114+ <NameEditComponent
115+ - - userName={this.state.userName}
116+ + + initialUserName="Javier Cansado"
117+ - - onChange={this.setUsernameState}
118+ + + onNameUpdated={this.setUsernameState}
119+ />
120+ a</div>
121+ );
122+ }
123+ }
124+ ```
108125
109- Now we've got a clear event, strongly typed and simplified (straight forward).
126+ Now we've got a clear event, strongly typed and simplified (straight forward).
110127
111128- Let's give it a try:
112129
113- ``` bash
114- npm start
115- ```
130+ ``` bash
131+ npm start
132+ ```
116133
117134- Then, load http://localhost:8080/ in a browser to see the output.
118135
119136 ![ Browser Output] (../99_readme_resources/04 Callback/browser_output.png "Browser Output")
120137
121- Now, the greeting only change when the user clicks on the change button.
138+ Now, the greeting only change when the user clicks on the change button.
139+
140+ ## Flow in the Components
141+
142+ * The main component ` <App/> ` is composed of two subcomponents.
143+ * ` <HelloComponent/> ` , it receives the state of _ userName_ (` userName={this.state.userName} ` ) with an initial value _ 'defaultUserName'_ , defined in ` this.state = { userName: 'defaultUserName' }; ` inside ` <App/> ` ( [ app.jsx] ( ./src/app.jsx ) )
144+ * ` <NameEditComponent/> ` , it receives a initial value for _ Username_ (` initialUserName="Javier Cansado" ` ) and a method (` onNameUpdated={this.setUsernameState} ` ) that change the value of _ Username_ state `setUsernameState(newName) {
145+ /* ...* /}`.
146+ * ` <HelloComponent/> ` , ( [ hello.jsx] ( ./src/hello.jsx ) ), show the value received into variable _ userName_ .
147+ * ` <NameEditComponent/> ` , ( [ nameEdit.jsx] ( ./src/nameEdit.jsx ) ), has two methods:
148+ * ` onChange(event){} ` , changes the 'value' each time it detects a change in the input ` <input value={this.state.editingName} onChange={this.onChange} id="editingName" /> ` .
149+ * ` onNameSubmit() {} ` , changes the state of _ editingName_ that will be uploaded to ` <App/> ` and giving to ` <HelloComponent/> ` .
0 commit comments