StochasticNerd StochasticNerd - 13 days ago 6
Javascript Question

Handling dropdown item select in React Bootstrap

I'm iterating through a dict and displaying the keys in a react-bootstrap dropdown menu.
This is my React dropdown Component,

class Dropdown extends React.Component{

constructor(props){
super(props);
this.onTargetSelect = this.onTargetSelect.bind(this);
}

onTargetSelect(target){
console.log("Outputting from here: ", target);
document.getElementById("dropdown-title").textContent(target);
this.props.passTargetToParent(target);
}

render(){
return(
<SplitButton title="Select Target" id="dropdown-target">
{Object.keys(dict).map(key => <MenuItem key={dict[key]} href={`#${dict[key]}`} onSelect={this.onTargetSelect(dict[key])}>{key}</MenuItem>)}
</SplitButton>
);
}

}


There are two things that I'm trying to do here, which are proving difficult because of my limited knowledge of Javascript.


  1. This displays all the values associated with the respective keys on load. That's not the behavior I want. I only want to console log the selected Item in the dropdown.

  2. Second I want to change the title displayed currently as
    Select Target
    to the selected item in the dropdown.


Answer

Change to this:

onSelect={() => this.onTargetSelect(dict[key])}

...what you have above is executing this.onTargetSelect() immediately during the render process, and thus once for each item in your list. You need to supply a handler (function) for onSelect, and that handler should call this.onTargetSelect() inside of it. The "() =>" syntax is creating a new function.

To change the title, you should not use the DOM as your are doing. In React, you modify state or props to cause a re-rendering of your component. Full code below using .state/.setState() (not tested, just copy/pasted from yours and tweaked):

class Dropdown extends React.Component {

  constructor(props) {
    super(props);
    this.onTargetSelect = this.onTargetSelect.bind(this);

    this.state = { title: 'Select Target' };
  }

  onTargetSelect(target) {
    this.setState({ title: target });

    this.props.passTargetToParent(target);
  }

  render() {
    return (
      <SplitButton title={this.state.title} id="dropdown-target">
        {Object.keys(dict).map(key => <MenuItem key={dict[key]} href={`#${dict[key]}`} onSelect={() => this.onTargetSelect(dict[key]) }>{key}</MenuItem>) }
      </SplitButton>
    );
  }

}