Reader small image

You're reading from  ReactJS by Example - Building Modern Web Applications with React

Product typeBook
Published inApr 2016
Reading LevelIntermediate
PublisherPackt
ISBN-139781785289644
Edition1st Edition
Languages
Right arrow
Author (1)
Vipul A M
Vipul A M
author image
Vipul A M

Vipul A M is Director at BigBinary. He is part of Rails Issues Team, and helps triaging issues. His spare time is spent exploring and contributing to many Open Source ruby projects, when not dabbling with React JS. Vipul loves Ruby's vibrant community and helps in building PuneRb, is the founder of and runs RubyIndia Community Newsletter and RubyIndia Podcast, and organizes Deccan Ruby Conference in Pune. He can be found @vipulnsward on twitter and on his site http://vipulnsward.com.
Read more about Vipul A M

Right arrow

Chapter 4. Composite Dynamic Components and Forms

In the previous chapter, we saw the various life cycle methods of a React component, how the data flows between React components, and how to manage state and props in our React application.

In this chapter, we will focus on multiple dynamic components and building forms using React.

We will cover following points:

  • Multiple dynamic components with interactivity

  • Controlled and uncontrolled components

  • Form elements

  • Form events and handlers

At the end of this chapter, we will be able to create applications containing complex forms using React with an understanding of the dynamic components.

Mike and Shawn are getting ready for their next project. The application is a prototype for an online bookstore where people can buy different books. Shawn is excited to work with Mike again and learn more about React. This project is based on React too.

Forms in React


"Shawn, in this project there will be many things related to placing an order, taking user's shipping and billing information, and so on. We are going to deal with a lot of forms now." started Mike.

"Forms using React, right?" Shawn asked excitedly.

"Yes. That is why today we will only focus on forms. Let's go through the intrinsic details of using forms using React." said Mike.

Setting up the application


"Shawn, we were using JSBin up to this point. But now we will create the app locally. We will use the following directory structure for our code:"

$ tree -L 1
.
├── LICENSE
├── README.md
├── index.html
├── node_modules
├── package.json
├── server.js
├── src
└── webpack.config.js

2 directories, 6 files
  • The src directory will contain all of the React components

  • The webpack.config.js and server.js file will be used for setting up local development server using webpack.

  • The package.json file will be used to contain information about all of the npm packages used by us

  • The index.html file will be the starting point of the app

"Let's see our index.html file."

// index.html
<html>
  <head>
    <title>Forms in React</title>
    <link rel="stylesheet"  href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
  </head>
  <body>
    <div id='root' class="container">
    </div>
  </body>
  <script...

Getting started with forms


"Forms behave slightly differently in the React world than in the normal HTML world. They are a bit special than the other DOM components in the React world. The <input>, <textarea>, and <option> tags are some of the common input components provided by React." explained Mike.

"These form components are mutated when the user interacts with them, adds some text in the input, or selects an option. Therefore, we need to take care that we are managing those user interactions properly." Mike explained further.

"Let's start with a simple input tag to understand the user interaction." informed Mike.

// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';

var InputExample = React.createClass({
  render() {
    return (
      <input type="text" value="Shawn" />
    );
  }
});
ReactDOM.render(<InputExample />,  
                 document.getElementById('root'));

"Mike, what is the meaning of import here?" asked Shawn.

"Good...

Interactive props


"Right. It also says that value is a prop. Similar to value, there are some other props supported by the input fields." said Mike.

  • value

  • defaultValue

  • onChange

"As React has warned us that we need to either provide the defaultValue or onChange prop to make this field mutable, let's take care of this and add a onChange handler. The field is read-only because by setting the value prop, we have rendered a controlled component." explained Mike.

Controlled components


"What is a controlled component, Mike?" asked Shawn.

"It's an input component whose value is controlled by React. By providing the value prop, we are informing React that the value of this field is "Shawn". Once React has declared it to be "Shawn", any user input won't have an effect as the value is already set in the ." explained Mike.

"I think that we have to resort to state instead of props?" Shawn asked.

"Exactly. As an user is interacting with the input field, we need to update the value prop using state and onChange event handler. Can you give it a try?" suggested Mike.

// src/index.js

var InputExample = React.createClass({
  getInitialState() {
    return (
      { name: '-'}
    );
  },

  handleChange(event) {
    this.setState({ name: event.target.value });
  },

  render() {
    return (
      <input type="text"
             value={this.state.name}
             onChange={this.handleChange} />
    );
  }
});

"Awesome. This pattern of making the value of...

Uncontrolled components


"React also has uncontrolled components where the value prop is not passed to the input".

render() {
    return (
      <input type="text" />
    );
  }

"In this case, the value entered by the user will be immediately reflected in the input. For setting some default initial value, we can pass the default value prop, which will act as the initial value for an uncontrolled component."

render() {
    return (
      <input type="text" defaultValue="Shawn"/>
    );
  }

"Awesome. This does it."

Getting started with form wizard


"Shawn, our task today is to build a form wizard, modeling all the steps that the user will take while using the online bookstore."

  • We will start with a form, where the user selects the book that they want to buy

  • In the next step, the user will enter the information related to the billing and shipping address

  • After this, the user needs to choose a delivery mechanism

  • In the end, the user will confirm the transaction and place the order

"Will we design four different forms then?" asked Shawn.

"Yes. But all of them will be controlled by a single parent. The parent component will keep a track of the state that the user is in and will render a form for this step." explained Mike.

// src/BookStore.js

import React from 'react';

var BookStore = React.createClass({
  render() {
    switch (step) {
      case 1:
        return <BookList />;
      case 2:
        return <ShippingDetails />;
      case 3:
        return <DeliveryDetails />;
    }
  }
})...

Form events


"Let's handle submitting the form now. React provides the onSubmit event for this purpose." said Mike.

// src/BookStore.js
……
// Updating BookStore component

render() {
    return(
      <div>
        <h3> Choose from wide variety of books available in our store </h3>
        <form onSubmit={this.handleSubmit}>
          {this.state.books.map((book) => { return (this._renderBook(book)) })}

          <input type="submit" className="btn btn-success" />
        </form>
      </div>
    );
  },

handleSubmit(event) {
    console.log(event);
    event.preventDefault();
    console.log("Form submitted");
   }
   ……

"Now, the next task is to get hold of all the books selected by the user. We can use state to achieve this." explained Mike.

// src/BookStore.js
……

// Updating BookStore component

getInitialState() {
    return (
      { books: [
        { id: 1, name: 'Zero to One', author: 'Peter Thiel' },
        { id: 2, name: 'Monk who sold...

Parent Child relationship


"Now after this, the next step is communicating with the parent component. Currently, there is no way that our child component can communicate with props. We want to communicate with the parent component as we want to send the selected books by the user to the parent component. The easiest way for a child to communicate with the parent is via props." Mike explained.

"But props are generally the attributes or properties that are sent to a child, right? How can a child communicate with the parent using them?" Shawn asked.

"Remember the {} syntax. We can pass any valid expression as prop. We can pass a function callback as prop to a child component. A child can call it to update the state of the parent. Let's update our BookStore component now." Mike explained.

// src/BookStore.js

……
// Updating BookStore component

  updateFormData(formData) {
    console.log(formData);
  },
  
  render() {
    switch (this.state.currentStep) {
      case 1:
        return <BookList...

Form validation


"Shawn, I think we should also add basic validation to the BookList component so that the user can't go to the next step without selecting a book," said Mike.

"Agree. Let me give it a try." answered Shawn.

// src/BookStore.js
// Updating BookList component

var BookList = React.createClass({
  getInitialState() {
    return (
      { books: [
        { id: 1, name: 'Zero to One', author: 'Peter Thiel' },
        { id: 2, name: 'Monk who sold his Fearrary', author: 'Robin Sharma' },
        { id: 3, name: 'Wings of Fire', author: 'A.P.J. Abdul Kalam' }
      ],
        selectedBooks: [],
        error: false
      }
    );
  },

  _renderError() {
    if (this.state.error) {
      return (
        <div className="alert alert-danger">
          {this.state.error}
        </div>
      );
    }
  },

  handleSubmit(event) {
    event.preventDefault();

    if(this.state.selectedBooks.length === 0) {
      this.setState({error: 'Please choose at least one book to continue...

Shipping details step


"Shawn, in this step, we want to get the user's shipping preferences. It will contain the shipping address and name of the customer." explained Mike.

"We should also add a phone number." Shawn added.

"Sure thing. Here is how our shipping details form look like." informed Mike.

// src/BookStore.js
// Adding ShippingDetails component

var ShippingDetails = React.createClass({
  getInitialState() {
    return (
      { fullName: '', contactNumber: '', shippingAddress: '', error: false }
    );
  },

  _renderError() {
    if (this.state.error) {
      return (
        <div className="alert alert-danger">
          {this.state.error}
        </div>
      );
    }
  },

  _validateInput() {
    if (this.state.fullName === '') {
      this.setState({error: "Please enter full name"});
    } else if (this.state.contactNumber === '') {
      this.setState({error: "Please enter contact number"});
    } else if (this.state.shippingAddress === '') {
      this.setState...

Delivery details step


"Shawn, the next step is about providing various delivery options. For now, let's assume that the user can choose between Primary delivery, meaning a next-day delivery, and Normal delivery, meaning 3 - 4 days delivery. By default, the Primary option must be selected. A user can choose the Normal delivery option too. Can you try building this last step?" Mike asked.

// src/BookStore.js
// Adding DeliveryDetails component

var DeliveryDetails = React.createClass({
  getInitialState() {
    return (
      { deliveryOption: 'Primary' }
    );
  },

  handleChange(event) {
    this.setState({ deliveryOption: event.target.value});
  },

  handleSubmit(event) {
    event.preventDefault();
    this.props.updateFormData(this.state);
  },

  render() {
    return (
      <div>
        <h1>Choose your delivery options here.</h1>
        <div style={{width:200}}>
          <form onSubmit={this.handleSubmit}>
            <div className="radio">...

Summary


In this chapter, we discussed how to develop forms in React. We saw how to use different input types and event handlers to respond to the user interaction for these inputs. We used state and props to manage the flow of form data from one step to another. We also saw how to use dynamic components to display particular form to the user based on the current step that the user is present on.

In the next chapter, we will continue with the form wizard and see how mixins can help us in organizing the code better.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
ReactJS by Example - Building Modern Web Applications with React
Published in: Apr 2016Publisher: PacktISBN-13: 9781785289644
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Vipul A M

Vipul A M is Director at BigBinary. He is part of Rails Issues Team, and helps triaging issues. His spare time is spent exploring and contributing to many Open Source ruby projects, when not dabbling with React JS. Vipul loves Ruby's vibrant community and helps in building PuneRb, is the founder of and runs RubyIndia Community Newsletter and RubyIndia Podcast, and organizes Deccan Ruby Conference in Pune. He can be found @vipulnsward on twitter and on his site http://vipulnsward.com.
Read more about Vipul A M