12

I've got an app that will be form-heavy, and I'd like as much control as possible, while using as few dependencies as I can. To do so, I'd like to take advantage of redux-form v6's custom Field component API and make a bunch of custom components that I can drop in at will. One of these components is a drop down select.

The problem is the custom drop down component does not connect to state, even though it renders OK.

In the docs, the examples accomplish this like:

<Field name="favoriteColor" component="select">
  <option></option>
  <option value="#ff0000">Red</option>
  <option value="#00ff00">Green</option>
  <option value="#0000ff">Blue</option>
</Field>

I'm looking for a plug-and-play approach where I can drop in a component, and feed into the props an array of data:

Form.js:

      <div className="form-group">
        <label htmlFor="dropDownSelect">Select an Option</label>
        <Field
          name="dropDownSelect"
          component={DropDownSelect}
          people={people}
          className="form-control"
        >
        </Field>
      </div>

DropDownSelect.js:

import React from 'react';

import styles from './styles.css';

class DropDownSelect extends React.Component { // eslint-disable-line react/prefer-stateless-function
  renderSelectOptions = (person) => {
    return (
      <option key={person} value={person}>{person}</option>
    );
  }

  render() {
    return (
      <select>
        {this.props.people.map(this.renderSelectOptions)}
      </select>
    );
  }
}


export default DropDownSelect;

When I check Redux DevTools, the field's value never populates when interacting with the dropdown:

enter image description here

I picked a value for both fields, but only 'effDate' populates a value, while 'dropDownSelect' remains as a registered field with no value.

Edit:

Based off the example, I guess the way to go about this is like:

function DropDownSelect(person) {
  return (
    <option key={person} value={person}>{person}</option>
  );
}

export default DropDownSelect;


      <div className="form-group">
        <label htmlFor="dropDownSelect">Select an Option</label>
        <Field
          name="dropDownSelect"
          component="select"
          // component={DropDownSelect}
          // people={people}
          className="form-control"
        >
          {people.map(DropDownSelect)}
        </Field>

This works for now, though it would be ideal if I could implement this as a completely separate component (as outlined in the initial question), so I can take advantage of lifecycle hooks in the case the field will depend on other fields.

1 Answer 1

16

To make separate custom component that handles drop down select, I needed to include the 'input' props to connect it to the form reducer:

Custom Component:

/**
*
* DropDownSelect
*
*/

import React from 'react';

import styles from './styles.css';

class DropDownSelect extends React.Component { // eslint-disable-line react/prefer-stateless-function

  renderSelectOptions = (person) => (
    <option key={person} value={person}>{person}</option>
  )

  render() {
    const { input, label } = this.props;
    return (
      <div>
        {/* <label htmlFor={label}>{label}</label> */}
        <select {...input}>
          <option value="">Select</option>
          {this.props.people.map(this.renderSelectOptions)}
        </select>
      </div>
    );
  }
}

// function DropDownSelect(person) {
//   return (
//     <option key={person} value={person}>{person}</option>
//   );
// }

DropDownSelect.propTypes = {
  people: React.PropTypes.array,
  input: React.PropTypes.object,
  label: React.PropTypes.string,
};

export default DropDownSelect;

Field:

      <div className="form-group">
        <label htmlFor="dropDownSelect">Select an Option</label>
        <Field
          name="dropDownSelect"
          // component="select"
          label="dropDownSelect"
          component={DropDownSelect}
          people={people}
          className="form-control"
        >
          {/* {people.map(DropDownSelect)} */}
        </Field>
      </div>
Sign up to request clarification or add additional context in comments.

3 Comments

How do you do custom rendering for errors. e.g. Appending something like this to show there's an error with the input. {touched && error && (<div role="alert" className="error">Error!</div>)}
How do you disabled the dropdown field in redux from?
@BharathMb The disabled prop is natively supported by HTML and can be dropped in as any other prop. With this example, you could pass in disabled as a prop through Field and drill it down into the <select> tag like: <select {...input} disabled={true}>...</select>

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.