React association (react-select)

Viewed 538

I was wondering how I can make associations in React (like in Rails). I want one company to have many contacts, and one contact to belong to a company. I have two separate models, Contact and Company, and when I'm creating Contacts I would like to select a Company where it belongs.

I was thinking of using react-select, where the dropdown menu will fetch all the Company names from the database.

I have actions/index.js where I get all the companies:

export const fetchCompanies = () => async dispatch => {
  const res = await axios.get('/api/companies');

    dispatch({type: FETCH_COMPANIES, payload: res.data.companies })
}

I import it inside the components/CompanyNew.js and try to make the dropdown menu. (I'm importing formField and ContactField from another file). If I put some dummy data according to the documentation it is displayed correctly. This is my code:

import { fetchCompanies } from '../../actions';
var Select = require('react-select');

class ContactNew extends Component {
    componentDidMount() {
            this.props.fetchCompanies();
    }

    const getOptions = (input) => {
      return this.props.fetchCompanies()
        .then((response) => {
          return response.json();
        }).then((json) => {
          return { options: json };
        });
    }


    renderFields() {
        return _.map(formField, ({ label, name }) => (
            <Field
                key={name}
                component={ContactField}
                type="text"
                label={label}
                name={name}
            />
        ));
    }
    onSubmit(values) {
        this.props.createContact(values, () => {
            this.props.history.push('/');
        });
    }

    render() {
        const { handleSubmit } = this.props;
        return (
            <div>
                <h3>Add new contact:</h3>
                <Form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
                    {this.renderFields()}
                    <Select.Async
                        name="form-field-name"
                        loadOptions={this.getOptions()}
                    />
                    <button type="submit">Save</button>
                </Form>
            </div>
        );
    }
}


export default reduxForm({
    form: 'contactForm',
    destroyOnUnmount: false
})(connect(null, { createContact })(ContactNew));

In Rails it's quite easy to do this, but I wouldn't know how to do this in React, because what I tried is not working.

1 Answers

two things I noticed,

first: it seems that you are expecting a return value from action

export const fetchCompanies = () => async dispatch => {
  const res = await axios.get('/api/companies');

  dispatch({type: FETCH_COMPANIES, payload: res.data.companies });
  return res; // missing return
}

second: I would think that you need to pass a function to Select.Async component instead of a promise this.getOptions vs this.getOptions()

<Select.Async
  name="form-field-name"
  loadOptions={this.getOptions}
/>

not sure if those are causing the problem you describe but may need to start there

Related