1

I have the following render function:

return (
  <div>
    <h1>Sign Up Sheet</h1>

    <form onSubmit={this.onFormSubmit}>

      <Field
        placeholder='Name'
        name='name'
        value={this.state.fields.name}
        onChange={this.onInputChange}
        validate={(val) => (val ? false : 'Name Required')}
      />

      <br />

      <Field
        placeholder='Email'
        name='email'
        value={this.state.fields.email}
        onChange={this.onInputChange}
        validate={(val) => (isEmail(val) ? false : 'Invalid Email')}
      />

      <br />

      <CourseSelect
        department={this.state.fields.department}
        course={this.state.fields.course}
        onChange={this.onInputChange}
      />

      <br />

      {{
        SAVING: <input value='Saving...' type='submit' disabled />,
        SUCCESS: <input value='Saved!' type='submit' disabled />,
        ERROR: <input
          value='Save Failed - Retry?'
          type='submit'
          disabled={this.validate()}
        />,
        READY: <input
          value='Submit'
          type='submit'
          disabled={this.validate()}
        />,
      }[this.state._saveStatus]}

    </form>

    <div>
      <h3>People</h3>
      <ul>
        { this.state.people.map(({ name, email, department, course }, i) =>
          <li key={i}>{[ name, email, department, course ].join(' - ')}</li>
        ) }
      </ul>
    </div>
  </div>
   );
  }
 };  

What is that for an expression?

  {{
    SAVING: <input value='Saving...' type='submit' disabled />,
    SUCCESS: <input value='Saved!' type='submit' disabled />,
    ERROR: <input
      value='Save Failed - Retry?'
      type='submit'
      disabled={this.validate()}
    />,
    READY: <input
      value='Submit'
      type='submit'
      disabled={this.validate()}
    />,
  }[this.state._saveStatus]}  

It is an object?

1

3 Answers 3

1

From the object based on the saved status it will return you the desired JSX element. For Instance if this.state._saveStatus is SAVING, it will return you <input value='Saving...' type='submit' disabled />

{{
    SAVING: <input value='Saving...' type='submit' disabled />,
    SUCCESS: <input value='Saved!' type='submit' disabled />,
    ERROR: <input
      value='Save Failed - Retry?'
      type='submit'
      disabled={this.validate()}
    />,
    READY: <input
      value='Submit'
      type='submit'
      disabled={this.validate()}
    />,
  }[this.state._saveStatus]}

You can think of the above like

render() {
    const obj = {
        SAVING: <input value='Saving...' type='submit' disabled />,
        SUCCESS: <input value='Saved!' type='submit' disabled />,
        ERROR: <input
          value='Save Failed - Retry?'
          type='submit'
          disabled={this.validate()}
        />,
        READY: <input
          value='Submit'
          type='submit'
          disabled={this.validate()}
        />,
      }

      return (
          <div>{obj[this.state._saveStatus]}</div>
       )
}

Now it is fairly inefficient to do what you are doing, since on each state change, a new element is returned. Instead what you need to do is change just the value and disabled attribute of input

return (
  <div>
    <h1>Sign Up Sheet</h1>

    <form onSubmit={this.onFormSubmit}>

      <Field
        placeholder='Name'
        name='name'
        value={this.state.fields.name}
        onChange={this.onInputChange}
        validate={(val) => (val ? false : 'Name Required')}
      />

      <br />

      <Field
        placeholder='Email'
        name='email'
        value={this.state.fields.email}
        onChange={this.onInputChange}
        validate={(val) => (isEmail(val) ? false : 'Invalid Email')}
      />

      <br />

      <CourseSelect
        department={this.state.fields.department}
        course={this.state.fields.course}
        onChange={this.onInputChange}
      />

      <br />

      <MessageField saveStatus={this.state._saveStatus} validate={this.validate()} />

    </form>

    <div>
      <h3>People</h3>
      <ul>
        { this.state.people.map(({ name, email, department, course }, i) =>
          <li key={i}>{[ name, email, department, course ].join(' - ')}</li>
        ) }
      </ul>
    </div>
  </div>
   );
  }
 };  


const MessageField = ({ saveStatus, validate }) => {
   const value = undefined;
   const disabled = true;
   switch(saveStatus) {
       case 'SAVING': value='Saving...';  disabled=true; break;
       case 'SUCCESS': value='Saved!'; disabled=true; break;
       case 'ERROR': value='Save Failed - Retry?';
          disabled=validate();
          break;
       case 'READY': value='Submit';
          disabled=validate();
          break;
   }
   return <input type={submit} disabled={disabled} value={value} />
}
Sign up to request clarification or add additional context in comments.

Comments

1

It is an object?

Yes. It's bracket notation, used to get the data by dynamic key.

If you break that, it will become:

const obj = {
    SAVING: <input value='Saving...' type='submit' disabled />,
    SUCCESS: <input value='Saved!' type='submit' disabled />,
    ERROR: <input
      value='Save Failed - Retry?'
      type='submit'
      disabled={this.validate()}
    />,
    READY: <input
      value='Submit'
      type='submit'
      disabled={this.validate()}
    />,
}

Then getting the value by this.state._saveStatus value:

{obj[this.state._saveStatus]}

Now just replace the obj with its content, you will get what you have written in the question. Basically that object contain the mapping of keys with JSX, and this.state._saveStatus will have any one key out of SAVING, SUCCESS, ERROR, READY. If you see the final result of that expression, then it will be any one JSX.

Comments

1

It's an object inside the usual {...} JSX expression notation used to embed values, which the code then picks a property from.

The code creates an object (the inner {}) and then looks up the property with the name in this.state._saveStatus on it; that becomes the value of the {...} expression.

So for instance, if this.state._saveStatus is "SUCCESS", the overall {...} expression evaluates to <input value='Saved!' type='submit' disabled />


It's a fairly inefficient way to do what it does. It creates an object and several elements (which involves function calls to React.createElement under the covers), just to discard them and keep the one it wants. Instead, an SFC would be a better choice (and reusable):

const StatusElement = props => {
    switch (props.status) {
        case "SAVING":
            return <input value='Saving...' type='submit' disabled />;
        case "SUCCESS":
            return <input value='Saved!' type='submit' disabled />;
        case "ERROR":
            return <input
                  value='Save Failed - Retry?'
                  type='submit'
                  disabled={props.disabled}
                />;
        case "READY":
            return <input
                  value='Submit'
                  type='submit'
                  disabled={props.disabled}
                />;
    }
};

then:

<StatusElement status={this.state._saveStatus} disabled={this.validate()} />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.