Step 8: Bringing in the user input

This step will focus on bringing all of the user input together in the App.

1. Adding a handler

As noted by the React documentation, forms work differently in React. First, try adding a handler for the Form component references in your Main component, along with the handleSubmit() method declaration:

src/Main.js
-        <Form>
+        <Form onSubmit={this.handleSubmit}>
  handleSubmit = (event) => {
    const { accessToken } = this.props;
    event.preventDefault();
  }

You'll notice that if you add a console.log(this.state); statement to the handleSubmit() method, you won't see any data that you could use to create an API request to the Achievers platform. The official React documentation explains how to get around this in their article, Lifting State Up. Start with your Reason component as it's simple and then apply the same idea to the Module and Recipient components.

src/Reason.js

First, update the render() method of the Reason component to have an onChange event handler:

   render() {
     return (
       <div className="reason">
         <Header as="h2" content="Personalize your message" />
-        <TextArea rows={5} placeholder='Give a reason for this recognition' />
+        <TextArea rows={5} placeholder='Give a reason for this recognition' onChange={this.handleChange} />
       </div>

2. Define the handler

Next define the handler, but use this.props instead of this.state.

  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.props.onReasonChange(e.target.value);
  }

In the Main component you need to make accompanying changes:

src/Main.js

First, update the render() method so it has an event handler:

     return (
       <div className='anywhereRecognition'>
           <Recipients accessToken={accessToken} />
-          <Reason />
+          <Reason onReasonChange={this.handleReasonChange} />

Define the handleReasonChange() method:

  handleReasonChange(reason) {
    this.setState({reason: reason});
  }

Finally, bind it in the constructor:

  constructor(props) {
    super(props);
+    this.handleReasonChange = this.handleReasonChange.bind(this);

    this.state = {
      isLoadingModules: true,
    }
  }

Now, you can do something like the following in the handleSubmit() method:

  handleSubmit = (event) => {
    const { accessToken } = this.props;
+    const { reason } = this.state;
+    console.log('reason: ' + reason);
    event.preventDefault();
  }

If you type a reason in the text area and click the "Post" button, the reason appears in the browser console.

3. Set up change event handlers

Apply the same idea to the other two components. Set up the change event handlers in the Main component for the Modules and Recipients components in the same way that you did for the Reason component.

src/Main.js

First, set the handlers on the components:

        <Form>
-          <Recipients accessToken={accessToken} />
+          <Recipients accessToken={accessToken} onRecipientsChange={this.handleRecipientsChange} />
          <Reason onReasonChange={this.handleReasonChange} />
-          <Modules modules={modules} />
+          <Modules modules={modules} onModuleCriterionChange={this.handleModuleCriterionChange} />

Define the handler methods:

  handleRecipientsChange(recipients) {
    this.setState({recipients: recipients.value});
  }

  handleModuleCriterionChange(criterionId) {
    this.setState({criterionId: criterionId});
  }

Bind the methods in the constructor:

  constructor(props) {
    super(props);
    this.handleReasonChange = this.handleReasonChange.bind(this);
+    this.handleModuleCriterionChange = this.handleModuleCriterionChange.bind(this);
+    this.handleRecipientsChange = this.handleRecipientsChange.bind(this);

    this.state = {
      isLoadingModules: true,
    }
  }

Update the Recipient component.

src/Recipient.js

Tap into the existing change handling function to set this.prop:

  handleRecipientsChange(e, { value }) {
    this.setState({ value });
+   this.props.onRecipientsChange({ value });  
  }

Then add a constructor to bind the method:

  constructor(props) {
    super(props);
    this.handleRecipientsChange = this.handleRecipientsChange.bind(this);
  }

Next, update the Module component.

src/Module.js

Set this.prop:

  handleCriterionClick = (e, titleProps) => {
    const { index, criteriaid } = titleProps
    const { activeCriterionIndex } = this.state
    const newIndex = activeCriterionIndex === index ? -1 : index
+   this.props.onModuleCriterionChange(criteriaid);
    this.setState({ activeCriterionIndex: newIndex })
  }

Add the binding in the constructor:

  constructor(props) {
    super(props);
+   this.handleCriterionClick = this.handleCriterionClick.bind(this);
    this.state = {
      activeModuleIndex: -1,
      activeCriterionIndex: -1,

Now if you go back to the Main component you can reference all three of these components:

  handleSubmit = (event) => {
    const { accessToken } = this.props;
+   const { reason, recipients, criterionId } = this.state;
+   console.log('reason: ' + reason + ' recipients: ' + recipients + ' criterionId: ' + criterionId);

    event.preventDefault();
  }

Now that you have access to everything you need, you're nearly done.