3

I'm new to React and Redux, so pardon me if the answer is trivial, but after an extensive search I don't seem to find a good answer to this simple question. I have multiple cascading selects where data getting populated based on the previous selection. Everything works fine when the user changes selected option. However, I can't figure out how to trigger onChange event when the data initially loaded in the first select? Here's the simplified component:

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { locationActions } from '../../_actions';
import { Input, Col, Label, FormGroup } from 'reactstrap';

class HeaderSetup extends React.Component {
  constructor(props) {
    debugger;
    super(props);        
    this.state = { location: 'Select an Option'};
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.loading !== this.props.loading &&
        nextProps.success !== this.props.success &&
        !nextProps.loading && nextprops.success) {
      this.setState({ location: '' });
    }
  }

  onLocationChanged(e) {
    console.log(e.target.value);    
  }

  render() {
    const { locations } = this.props;
    return (
      <FormGroup row>
        <Label for="locations" sm={3}>Locations</Label>
        <Col sm={8}>
        {locations.items &&                    
          <Input type="select" name="locations" id="locations" 
                onChange={this.onLocationChanged} 
                value={this.state.location}>
              {locations.items.map((location, index) =>
                  <option key={location.id}>
                      {location.locationName}                                
                  </option>
              )}
          </Input>
          }          
        </Col>
      </FormGroup>       
    )
  }
}

function mapStateToProps(state) {
  debugger;
  const { locations } = state;
  return {
    locations
  };
}

export default connect(mapStateToProps)(HeaderSetup); 

Do I just need to trigger it manually? If so, what's the best place/way to do that? Any help is greatly appreciated!

2
  • does your console log work? Commented Mar 1, 2018 at 19:42
  • @Omar - It does when I change select option. Not on initial load. Commented Mar 1, 2018 at 19:43

1 Answer 1

3

Since you are using controlled components they should always reflect the state. In your onChange callback you should just update the state and all the inputs should update accordingly.

If you put up a minimal working example showing this issue I might be able to provide more details.

Below is a simple working example of how to set this up:

class App extends React.Component {
  state = {
    locations: []
  };
  componentDidMount() {
    setTimeout(() => { // simulate loading
      this.setState({
        loading: false,
        locations: [
          {
            id: 1,
            label: "Paris"
          },
          {
            id: 2,
            label: "Rome"
          }
        ]
      });
    }, 3000);
  }
  render() {
    return <MyForm locations={this.state.locations} initialLocation={2}/>;
  }
}

class MyForm extends React.Component {
  state = {
    initialLocation: null,
    location: ""
  };

  componentWillReceiveProps(nextProps) {
    this.setState({
      initialLocation: nextProps.initialLocation,
    })
  }
  
  onChange = e => {
    this.setState({
      location: e.target.value
    });
  };

  render() {
    const { locations } = this.props;
    return (
      <label>
        <div>Select a location:</div>
        {locations.length > 0 && (
          <select value={this.state.location || this.state.initialLocation} onChange={this.onChange}>
            {locations.map(({ id, label }) => (
              <option key={id} value={id}>
                {label}
              </option>
            ))}
          </select>
        )}
      </label>
    );
  }
}

ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @thedude, but I've tried that and it's working just fine when select is triggered by user. The problem is that it's not getting triggered when the first select is initially populated. I need the default trigger the 2nd select. I'll put the working example, but it's kinda hard show the problem as it's only initial load that I have issue with.
@lentyai I've updated the example to show how you can pass an initialLocation

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.