chobo2
chobo2

Reputation: 85765

How to Update This Reactjs Select

I have this wrapper class that is used because I am using Formik and the FieldArray

import React, { Component } from "react";
import { ReactDOM } from "react-dom";
import Select from "react-select";
import { observer } from "mobx-react";
import { axiosInstance } from "../stores/AxiosInstance";

@observer
export default class CountryStateSelectComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { stateOptions: [] };
  }
  handleCountryChange = value => {
    const that = this;

    axiosInstance
      .get(`/States?countryId=${value.value}`)
      .then(function(response) {
        that.props.onChange(that.props.countryName, value);
        that.props.onChange(that.props.stateName, null);

        const states = response.data.map(state => {
          return { label: state.name, value: state.id };
        });
        // if I move out state select code then won't need to update state here but don't know how to call something like updateState(record)
        that.setState({
          stateOptions: states
        });
      });
  };
  handleStateChange = value => {
    console.log(this.props.stateName, value)
    this.props.onChange(this.props.stateName, value);
  };
  handleCountryBlur = () => {
    this.props.onBlur(this.props.countryName, true);
  };
  handleStateBlur = () => {
    this.props.onChange(this.props.stateName, true);
  };
  render() {
    const props = this.props;
    return (
      <React.Fragment>
        <div className="field">
          <label className="label">Country</label>
          <div className="control">
            <Select
              options={props.options}
              isMulti={props.isMulti}
              onChange={this.handleCountryChange}
              onBlur={this.handleCountryBlur}
              closeMenuOnSelect={props.closeMenuOnSelect}
            />
            {this.props.CountryError}
          </div>
        </div>

        <div className="field">
          <label className="label">State/Province</label>
          <div className="control">
            <Select
              options={this.state.stateOptions}     
              onChange={this.handleStateChange}
              onBlur={this.handleStateBlur}
            />
            {this.props.StateError}
          </div>
        </div>
      </React.Fragment>
    );
  }
}

However what I found is that when the State gets selected the value does not get stored in Formik(it gets stored as undefined and sometimes true).

So now I am thinking maybe moving out the State Zip out and making it's own wrapper or something but I don't know how to get the "states" that came back and populate the correct state box as they can generate many.

@inject("AccountSetupStore")
@observer
export default class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { records:  [this.generateRecord(1, true, true)] };
  }
  componentDidMount() {
    const accountSetupStore = this.props.AccountSetupStore;
    accountSetupStore.getCountries();
  }
  updateState(record) {
      // would like to call this method that can somehow update the record
      // propblem is I don't seem to have access to props when this function is being called from the CountryStateSelectComponent
  }
  render() {
    const props = this.props;
    const accountSetupStore = props.AccountSetupStore;

    const countries = [];
    for (const country of accountSetupStore.countries) {
      countries.push({ value: country.id, label: country.name });
    }


    return (
      <section className="accordions">
        <Formik
          initialValues={{
            records: this.state.records
          }}
          onSubmit={(
            values,
            { setSubmitting, setErrors}
          ) => {

            console.log(values,"values");
          }}
          validationSchema={Yup.object().shape({
            branches: Yup.array()
              .of(
                Yup.object().shape({
                })
              )
          })}
          render={({
            values,
            setFieldValue,
            setFieldTouched,
          }) => (
            <FieldArray
              name="records"
              render={arrayHelpers => (
                <Form>
                  {values.records.map((record, index) => {
                     return (<article}>
                       <CountryStateSelectComponent options={countries} 
                                onChange={setFieldValue}
                                countryName={`records[${index}].selectedCountry`}
                                stateName={`records[0].selectedState`}
                                onBlur={setFieldTouched}
                                isMulti={false}
                                index = {index}
                                closeMenuOnSelect={true}
                                CountryError = {<ErrorMessage name={`records[${index}].selectedCountry`}/>}
                                StateError= {<ErrorMessage name={`records[${index}].selectedState`}/>}
                            />
                   </article>)
                  })}
                </Form>
              )}
            />
          )}
        />
      </section>
    );
  }
}

Upvotes: 1

Views: 355

Answers (1)

Steve -Cutter- Blades
Steve -Cutter- Blades

Reputation: 5432

React Select onChange sends the value to the method supplied

const onStateChange = (selectedOption, {action}) => {
  //do something with the selectedOption according to the action
}

<Select onChange={onStateChange} />

See the documentation for the onChange in the Props documentation.

Upvotes: 1

Related Questions