reactjsweb-componentreact-componentselect-options

Radio button not updating correctly based on change in Select option in React


I am having a Select drop-down with 2 options and a radio button with 2 values. (Refer Code below) When the page is loaded, "Quadrant 1" is the default Select option and none of the radio button will be selected on default.

For "Quadrant 1" of select option, I will select "No" in the radio button. For "Quadrant 2" of select option, I will select "Yes". These values are stored in "Grid" state correspondingly. I am able to successfully capture these updates in state whenever the changes are made.

But when I switch between the select options, the radio button is not changed correspondingly. I know I have to update the "checked" property of the radio button whenever Select option is changed. But I am not able to do that. Pardon me if I am wrong since I am new to ReactJS and hitting my head for the past 1 week.

Please help me to update the radio button whenever the select option in changed.

Updated RuleScreen.js:

[Correct Grid State details but radio button not updated][1]
import React, { Component } from "react";
import M from "materialize-css";
import dropDownList from "./dropDown";
import _ from "lodash";

class RuleScreen extends Component {

  constructor(props){
    super(props);
    this.state = {
      quad: "Q1",
      grid: [{id:"Q1", optin:"",NL:""}, {id:"Q2", optin:"", NL:""}]
    };
  }

  componentDidMount() {
    var elems = document.querySelectorAll('select');
    M.FormSelect.init(elems, {hover: true, coverTrigger: false});
  }

  quadChange = async (e) => {
    await this.setState({ quad:e.target.value});
  }

  optinChange = async (e) => {
    const currQuad = this.state.quad;
    const value = e.target.value;
    await this.setState(prevState => ({
      grid: prevState.grid.map(
        item => item.id === currQuad? { ...item, optin: value}: item
      )
    }))
  }

  render() {
    const selectedGrid = this.state.grid.filter(quad=>quad.id === this.state.quad)
    return (
      <div>
        <h3>Rule Setup</h3>
        <div className="container">
          <div className="btn">
            <select required value={this.state.quad} onChange={this.quadChange}>
              <option key="Q1" value="Q1">Quadrant 1</option>
              <option key="Q2" value="Q2">Quadrant 2</option>
            </select>
          </div>
          <form>
            <label>Opt In</label>
            <label><input id="yes" checked={selectedGrid[0].optin=== 'yes' } onChange={this.optinChange} value="yes" className="with-gap" name="optin" type="radio"/>
                <span>Yes</span>
            </label>
            <label><input id="no" checked={selectedGrid[0].optin=== 'no' } onChange={this.optinChange} value="no" className="with-gap" name="optin" type="radio"/>
                <span>No</span>
            </label>
          </form>
        </div>
      </div>
    );
  }
}


export default RuleScreen;


Solution

  • Since You use array functions, you dont have to bind function to 'this'. I haven't test the code but the idea is here. Add value to radio button, remove the getter for values, add a selector to grid in render

    class RuleScreen extends Component {
    
          constructor(props){
            super(props);
            this.state = {
              quad: "Q1",
              grid: [{id:"Q1", optin:"", NL:""}, {id:"Q2", optin:"", NL:""}]
            };
          }
    
          componentDidMount() {
            var elems = document.querySelectorAll('select');
            M.FormSelect.init(elems, {hover: true, coverTrigger: false});
          }
    
          quadChange = (e) => {
            this.setState({ quad:e.target.value});
          }
    
          optinChange = (e) => {
            const currQuad = this.state.quad;
            const value = e.target.value;
            this.setState(prevState => ({
              grid: prevState.grid.map(
                item => item.id === currQuad? { ...item, optin: value}: item
              )
            }))
          }
          
    
          render() {
            const selectedGrid = this.state.grid.filter(quad=>quad.id === this.state.quad) //maybe with [0] at the end
            return (
              <div>
                <h3>App Name</h3>
                <div className="container">
                  <div className="btn">
                    <select required value={this.state.quad} onChange={this.quadChange}>
                     <option key="Q1" value="Q1">Quadrant 1</option>
                     <option key="Q2" value="Q2">Quadrant 2</option>
                    </select>
                  </div>
                  <form>
                    <div>Opt In</div>
                    <label>
                      <input id="yes" checked={selectedGrid.optin === 'yes'} onChange={this.optinChange} value="yes" className="with-gap" name="optin" type="radio"/>
                        <span>Yes</span>
                    </label>
                    <label>
                      <input id="no" checked={selectedGrid.optin === 'no'} onChange={this.optinChange} value="no" className="with-gap" name="optin" type="radio"/>
                        <span>No</span>
                    </label>
                  </form>
              </div>
            )
          }
    }
    
    
    export default RuleScreen;