ryanpitts1
ryanpitts1

Reputation: 894

React select onChange not changing selected value

I have a React component that has some html rendered and part of the html is a select element. The below code works for displaying the default value of the initial select element and changes the selected value when you choose another one.

My problem is that i have a list of people and when you click on one the values on the section of the page where this is used get updated to that person's values (name, email, etc). Those all update correctly i believe because this.props.agent gets updated. I don't have insight into that code at the moment. My question is that the select element isn't respecting the change in this.props.agent and thus re-selecting the correct saved value for team. I'm sure using state within constructor() isn't the right approach.

I am new to React so pardon me if my question isn't accurate or explained well enough. But how can i get it to update the pre-selected select option when this.props.agent updates?

import React from 'react'
import axios from 'axios'

export class AgentTeam extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            teams: [],
            selectedTeam: this.props.agent.team || ''
        }

        this.handleOnClick = this.handleOnClick.bind(this)
        this.handleOnChange = this.handleOnChange.bind(this)
    }

    componentDidMount() {
        axios.get(
            ... ajax setup ...
        ).then(response => {
            this.setState({
                teams: response.data,
            })
        }).catch(error => {
            throw error
        })
    }

    handleOnClick() {
        const selectedTeam = document.querySelector('.team-selection').value

        axios.post( ...ajax stuff... )
    }

    handleOnChange = (event) => {
        this.setState({
            selectedTeam: event.target.value
        })
    }

    render() {
        const teamList = this.state.teams.map((team, i) =>
            <option value={team.team_name} key={i}>
                {team.team_name}
            </option>
        )

        return (
            <div>
                <div className='agent-team-heading'>
                    <span>Team</span>
                </div>
                <div className='agent-team-selector'>
                    <select className='team-selection' value={this.state.selectedTeam} onChange={this.handleOnChange}>
                        <option value=''>Assign Team</option>
                        {teamList}
                    </select>
                    <button className="agent-team-button" onClick={this.handleOnClick}>
                        <span>SAVE</span>
                    </button>
                </div>
            </div>
        )
    }
}

Upvotes: 2

Views: 13158

Answers (2)

Dadsquatch
Dadsquatch

Reputation: 566

Need to tell React to trigger the function onClick

onClick={() => this.handleOnClick()} <-----

Just a side note to help save on code, you can also use ES6 to bind functions to this by doing an arrow function. It's not 100% for sure if it will be there in the future, but it's widely used so I think they will adopt it.

handleOnClick = () => {
  const selectedTeam = document.querySelector('.team-selection').value

  axios.post( ...ajax stuff... )
}

Upvotes: 1

Toby
Toby

Reputation: 13385

You can use componentDidUpdate() to check if incoming props are different:

componentDidUpdate(nextProps) {
  if (nextProps.agent.team !== this.props.agent.team) {
    this.setState({ selectedTeam: nextProps.agent.team })
  }
}

In componentDidUpdate, nextProps represents the incoming props. This will check if they are different, and the setState will ensure the component re-renders.

Additionally, this will run when the component first receives props, meaning you shouldn't have to set the default value in state.

Note: You are mixing methods, by using querySelector to get the value of the select menu. Ideally, you would use the value in state - that way you can ensure that you are setting and getting the right value, rather than mixing methods and possibly getting the non-updated version.

Upvotes: 3

Related Questions