Jonathan Small
Jonathan Small

Reputation: 1079

reactJS and <select> results in Cannot read property 'selectedIndex' of null

I have a reactJS application where I render a drop down select with the following code:

renderPrimary = (passedid,value) => {  

    if (value=="Primary") {
        return (      
            <div className="col-9 text-left text_14">
                <select id={passedid}>
                    <option value="Primary" selected>Yes</option>
                    <option value="Secondary">No</option>
                </select>
            </div>
        )
    } else {
        return (      
            <div className="col-9 text-left text_14">
                <select id={passedid}>
                    <option value="Primary">Yes</option>
                    <option value="Secondary" selected>No</option>
                </select>
            </div>
        )
    }
}

This will render a drop down with two values, either Primary or Secondary based on the passed parameter 'value'. In my first test case, value = "Primary" so the code with render the with a drop down with "Yes" and "No" and the "Yes" is selected.

When the user clicks on a button, I validate other elements in the DOM. I then try to pick up the value from the so I know if the user selected Yes or No. I do this with the following code:

            if (formIsValid) {
                var id = "benePorS"+(l+1);
                var element = document.getElementById(id);
                var id2 = "benePct"+(l+1);
                var element2 = document.getElementById(id2);

                var PorS = element.selectedIndex;
                console.log("PorS: ", PorS);
                if (PorS == 0) {
                    hasPrimary = true;   
                    primaryPct = primaryPct + element2.value;                     
                } else {
                    hasSecondary = true;
                    secondaryPct = secondaryPct + element2.value;  
                }
            }

When I execute the code, I see the following in the console.log:

PorS:  0

but then I see this:

Uncaught TypeError: Cannot read property 'selectedIndex' of null
at Beneficiaryupdate.SaveBeneficiaryInformation

So it seems that I can access the selected value (when I select No, I see PorS: 1 in the console.log) but the error prevents the code from continuing.

This is from the developers tool elements tab showing the rendered html:

enter image description here

Why would I be getting this error message?

Upvotes: 0

Views: 2172

Answers (1)

Emmanuel Argollo
Emmanuel Argollo

Reputation: 71

Since you are using react, there should be better ways to handle your <select>

First:

You don't need to use the selected attribute in react's select tag. As stated in the docs, you could simply pass the selected value in the root select tag, like so:

renderPrimary = (value) => {
    return (      
                <div className="col-9 text-left text_14">
                    <select value={value} >
                        <option value="Primary">Yes</option>
                        <option value="Secondary">No</option>
                    </select>
                </div>
            );
}

Second:

Since you're setting a value property, you should add a onChange property to handle the user interaction:

constructor(props) {
    super(props);
    this.state = {
        selectedValue: "Primary"
    };
}

handleValueSelected = (event) => {
    this.setState({selectedValue: event.target.value});
}

renderPrimary = () => {
    return (      
                <div className="col-9 text-left text_14">
                    <select value={this.state.selectedValue} 
                            onChange={this.handleValueSelected}>
                        <option value="Primary">Yes</option>
                        <option value="Secondary">No</option>
                    </select>
                </div>
            );
}

That way, wherever you need the selected value in your component, you can just access this.state.selectedValue.

Third:

If you really need to get the DOM of this select, or any other elements, you can use react's ref, like:

constructor(props) {
    super(props);
    this.state = {
        selectedValue: "Primary"
    };
    this.selectRef = React.createRef();
}
handleValueSelected = (event) => {
    this.selectedValue = event.target.value;
}

renderPrimary = () => {
    return (      
                <div className="col-9 text-left text_14">
                    <select ref={this.selectRef} 
                            value={this.state.selectedValue} 
                            onChange={this.handleValueSelected}>
                        <option value="Primary">Yes</option>
                        <option value="Secondary">No</option>
                    </select>
                </div>
            );
}

And with this, this.selectRef should have the DOM once the component is mounted, but you shouldn't really need to access the DOM much with react.

Upvotes: 1

Related Questions