Chapter 6: JavaScript Ecosystem
Activity 6 – Building a Frontend with React
The frontend team working on your note-taking app from Exercise 35 has unexpectedly quit. You must build the frontend for this application using React. Your frontend should have two views: a Home view and an Edit view. Create a React component for each view. The Home view should have a button that changes the view to the Edit view. The Edit view should have a button that switches back to the Home view, a text input that contains the note text, a load button that calls the API load route, and a save button that calls the API save route. A Node.js server has been provided. Write your React code in activities/activity6/activity/src/index.js. When you are ready to test your code, run the build script (defined in package.json) before starting the server. You can reference the index.html file from Exercise 35 for hints on how to call the API routes.
To build a working React frontend and integrate it with a Node.js express server, follow these steps:
- Begin working in "activity/activity6/activity". Run - npm installto install the required dependencies.
- In src/index.js, create React components called - Homeand- Editor.
- Add a constructor to the App react component. In the constructor: - Take in the - propsvariable. Call- superand pass- propsinto- super.- Set the - stateobject in the- thisscope. It must have a property called- viewwith the value- home.
- Add a - changeViewmethod to the app.- The - changeViewmethod should take in a parameter called- view.- Update the state with - setStateand set the- viewproperty of the- stateequal to the provided parameter- view.- In the constructor, add a line that sets - this.changeViewequal to- this.changeView.bind(this).
- In App’s - renderfunction, create a conditional rendering based on the value of- this.state.viewthat does the following:- If - state.viewis equal to- home, show the home view. Otherwise, show the editor view.- Pass the - changeViewfunction as a parameter to both views, which are- <Editor- changeView={this.changeView}/>and- <Home changeView={this.changeView}/>.
- In the - Homecomponent, add a- goEdit()function, which- callsthe- changeViewfunction passed in through- props(- this.props.changeView). and passes in the string- editorto the- changeViewfunction.
- Create the - renderfunction in the- Homecomponent:- Return a JSX expression. - To the returned JSX expression, add a - divthat contains a title heading- titleof the app- Note Editor App, and add a button that changes the view to the- Editview.- The button should call the - goEditfunction on click. Be sure to properly bind the- thisstate to the- goEditfunction.
- Add a constructor to the - Editorcomponent:- Take in the - propsparameter- Call - superand pass in the- propsvariable.- Set the - statevariable in the- thisscope equal to the- {value: ‘’}object.
- Add a function called - handleChageto- Editor:- Takes in an argument, - e, that represents the event object.- Update the state with - setStateto set the state property- valueequal to the event target’s value:- this.setState( { value: e.target.value } );
- Create a - savefunction in- Editorthat makes an HTTP request to the API save route.- Create a new XHR request and save it into the - xhttpvariable.- Set the - xhttpproperty- onreadystatechangeto a function that checks if this.- readyStateis equal to- 4. If it is not, then return. Also, check if- this.statusis equal to- 200. If it is not, then throw an error.- Open the - xhrrequest by calling the- openfunction on- xhttp. Pass in the parameters- POST,- /save, and- true.- Set the request header - Content-Typeto- application/json;charset=UTF-8by calling the- setRequestHeaderon the- xhttpobject. Pass in the values specified.- Send the JSON data of the text input with - xhttp.send.- The value to which, we must send is stored in - this.state. Stringify the value before sending it.
- Create a - loadfunction in- Editorthat makes an HTTP request to the API load route.- Create a new XHR request and save it into the - xhttpvariable.- Save the - thisscope into a variable called- thatso that it can be used inside the- xhrrequest.- Set the - xhttpproperty- onreadystatechangeto a function that checks if- this.readyStateis equal to- 4. If it isn’t, then return. It then checks if- this.statusis equal to- 200. If it is not, then throw an error. It calls the- setStatefunction on the React component’s scope, which is saved in the- thatvariable.- Pass in an object with the key - valueequal to the parsed response of the request. Parse the HTTP response value from the- this.responsevariable with the- JSON.parsefunction.- Open the HTTP request by calling the - openfunction on the- xhttpvariable. Pass in the parameters- GET,- /load, and- true.- Send the XHR request by calling the - send()method on the- xhttpobject.
- Create a - goHomefunction in- Editor.- Call the - changeViewfunction that was passed in through the React element properties object (- this.props.changeView()).- Pass in the string - home.
- Create the - renderfunction in- Editor.- Add a button that, once clicked, calls the - goHomefunction that contains the text- Back to home. It calls the- goHomefunction on the click event. Make sure to properly bind the- thisscope to the function.- Add a - textinput that contains the note text. The text input loads its value from the- state.valuefield. The- textfield calls the- handleChangefunction on a change event. Make sure to properly bind the- thisscope to the- handleChangefunction.- Add a button to load the note data from the server that contains the text - Load. It calls the- loadfunction on the click event. Be sure to properly bind the- thisscope to the load function call.- Add a button to save the note data to the server that contains the text - Save. It calls the- savefunction on the click event. Be sure to properly bind the- thisscope to the save function call.- Be sure to bind the - thisstate properly to all listeners.
- Test the code when ready by doing the following: - Running - npm run buildin the root project folder to transpile the code from JSX.- Running - npm startto start the server.- Loading the URL specified when the server start ( - 127.0.0.1:PORT).- Testing the view changes by clicking the Edit and - Back to homebuttons.- Testing the - savefunctionality by entering text into the- textinput, saving it, and checking the text file that was created in the folder to see if it matches.- Testing the - loadfunctionality by entering text into the text file, loading it, and making sure that the value in the- textinput matches the value in text file.
A condensed snippet is provided in the following snippet. Refer to activities/activity6/solution/src/index.js for the full solution code.
Index.js
class Editor extends React.Component {
 constructor( props ) { ... }
 handleChange( e ) { ... }
 save() { ... }
 load() { ... }
 goHome() { ... }
 render() {
   return (
     <div>
       <button type="button" onClick={this.goHome.bind( this )}>Back to home</button>
       <input type="text" name="Note Text" value={this.state.value} onChange={this.handleChange.bind( this )}/>
       <button type="button" onClick={this.load.bind( this )}>Load</button>
       <button type="button" onClick={this.save.bind( this )}>Save</button>
     </div>
   );
 }
}
class Home extends React.Component {
 goEdit() { ... }
 render() {
   return (
     <div>
       <h1>Note Editor App</h1>
       <button type="button" onClick={this.goEdit.bind( this )}>Edit Note</button>
     </div>
   );
 }
}
//{…}Snippet 6.42: React component
Outcome:
Take a look at the output screenshots here:

Figure 6.13 : Edit view

Figure 6.14 : Server view

Figure 6.15 : Running the server to test code
You have successfully built a working React frontend and integrated it with a Node.js express server.
 
                                             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
     
         
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                