1

So I am pulling a list of companies from Firestore and trying to map them into selections in a dropdown list. The companies state is populating right from Firestore, but my options are not being created / updated. How do I get the options to dynamically populate?

My state and db pull:

constructor(props) {
    super(props);
    this.state = {
      db: '',
      companies: [],
      jobs: [],
      company: 'Company',
      job: 'Job'
    };
  }

  componentDidMount() {
    this.db = firestore.firestore();
    this.db.collection("companies")
    .get()
    .then(querySnapshot => {
      const data = querySnapshot.docs.map(doc => doc.data());
      console.log(data);
      this.setState({ companies: data });
    });
  }

Where I attempt to create the options (based on this stack post I found):

createCompanySelections() {
    var company_selections = [];
    if(this.companies) { 
      company_selections = this.companies.map((Name) => <option key={Name}>{Name}</option>);
    }
    return company_selections
  }

Where I try to insert the selections (using materialUI):

<FormControl>
   <InputLabel htmlFor="companies">Companies</InputLabel>
   <NativeSelect
    variant='standard'
    value={this.state.company}
    onChange={this.updateInput}
    inputProps={{
      name: 'company',
    }}
   >
     {this.createCompanySelections()}
  </NativeSelect>
</FormControl>

1 Answers1

2

// updated answer for a cleaner solution It looks like your component doesn't re-render on that change, so to make sure it does pick up the change just pass new data in render.

constructor(props) {
  super(props);
  this.state = {
    db: '',
    companies: [],
    jobs: [],
    company: 'Company',
    job: 'Job'
  };
 }

 componentDidMount() {
    this.db = firestore.firestore();
    this.db.collection("companies")
    .get()
    .then(querySnapshot => {
      const data = querySnapshot.docs.map(doc => doc.data());
      console.log(data);
      // set copmany options on state, so component re-renders once they are set
      this.setState({ 
        companies: data,
      });

    });
  }

// looks like you always pass an array 
  createCompanySelections(companies) {
     return companies.map((Name) => <option key={Name}>{Name}</option>);
  }

And in Form control do something like:

 {!!this.companies.length && (
    <FormControl>
    <InputLabel htmlFor="companies">Companies</InputLabel>
      <NativeSelect
        variant='standard'
        value={this.state.company}
        onChange={this.updateInput}
        inputProps={{
          name: 'company',
        }}
      >
        {this.createCompanySelections(this.companies)}
      </NativeSelect>
    </FormControl>
  )}
Uma
  • 836
  • 5
  • 7