3

What I want to do is get the value of the selected <option> from the <select> elemenet however in my current code, I keep getting an error saying:

cannot read property 'value' of null.

This is very frustrating considering I've tried the methods I found online and yet it still doesn't work properly. Any help would be appreciated, thanks!

import React, { Component } from 'react'

class MyClass extends Component{
    constructor(props){
        super(props);

        this.state = {
            selectedItem: ""
        };
    }

    onChange() {
        var selectedItem = document.getElementById("selectItem").value
        this.setState({selectedItem: selectedItem})
    }

    render(){
        return (
            <div style={{textAlign: "center"}}>
                <select id="selectItem" defaultValue="option1" onChange={this.onChange()}>
                    <option value="option1">option1</option>
                    <option value="option2">option2</option>
                    <option value="option3">option3</option>
                    <option value="option4">option4</option>
                </select>

                <div>{this.state.selectedItem}</div>
            </div>
        )
    }
}

export default MyClass

I would like it to display what option is being selected within the div. If possible I would also like it to show the defaultValue upon loading the page as well.

2
  • You're calling the function (onChange={this.onChange()}). You should use onChange={this.onChange}, in any case, using document.getElementById in a ReactJS app is not the way to go. Commented Aug 21, 2019 at 0:12
  • @Titus if you could show your solution to not using getElementById that would be awesome. I would like to eliminate it if I can, just the only way I know how to get that value atm. Commented Aug 21, 2019 at 0:26

2 Answers 2

2

The reason this isn't working is because the context of onChange is not that of your MyClass component instance, meaning that when onChange is called, this won't be the corresponding instance of MyClass.

The problem can be resolved by adding this line to your constructor:

constructor(props){
    super(props);

    this.state = {
        selectedItem: ""
    };

    // Add this
    this.onChange = this.onChange.bind(this);
}

Update

One way to load the default value of the <select> dynamically:

class MyClass extends Component{
    constructor(props){
        super(props);

        this.state = {
            selectedItem: ""
        };
    }

    componentDidMount() {

        /* Set initally selected value to say, option3 */
        this.setState({ selectedItem : "option3" })
    }

    onChange() {
        var selectedItem = document.getElementById("selectItem").value
        this.setState({selectedItem: selectedItem})
    }

    render(){
        return (
            <div style={{textAlign: "center"}}>
                {/* 
                Specify the select value which will show as option3 by
                default 
                */}
                <select id="selectItem" value={ this.selectedItem }
                        onChange={this.onChange()}>
                    <option value="option1">option1</option>
                    <option value="option2">option2</option>
                    <option value="option3">option3</option>
                    <option value="option4">option4</option>
                </select>

                <div>{this.state.selectedItem}</div>
            </div>
        )
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome this worked! Is there any way that I can load the defaultValue upon loading my page via componentDidMount()? Or will that not work?
@Michael you're welcome - just updated answer, does that help?
1

The problem is that you're calling this.onChange while the element is created, while the onChange attribute is set (onChange={this.onChange()}).

You should use just onChange={this.onChange} (without the parenthesis ()).

Beside that, document.getElementById is not how you access the DOM in a ReactJS app, actually, you don't need to access the DOM in this case.

import React, { Component } from 'react'


class MyClass extends Component{
    state = {
        selectedItem: ""
    };

    onChange = ({ target: { value } }) => {
        this.setState({ selectedItem: value })
    }

    render(){
        return (
            <div style={{textAlign: "center"}}>
                <select id="selectItem" defaultValue="option1" onChange={this.onChange}>
                    <option value="option1">option1</option>
                    <option value="option2">option2</option>
                    <option value="option3">option3</option>
                    <option value="option4">option4</option>
                </select>

                <div>{this.state.selectedItem}</div>
            </div>
        )
    }
}

export default MyClass

1 Comment

Thank you for sharing your answer!

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.