Search code examples
javascriptreactjsreact-table

React initial state: 2 Radio Buttons in each row of a Table


I have a table with 2 radio buttons in each row to either approve or reject the row. The onChange event saves the ID of each row and if it was approved or rejected. There is then a button to save this in the back end.

That all works fine.

    import React from 'react';
    import { Button } from 'reactstrap';

    class ApproveDataList extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            changedValues : {}
        };
    }

    onChange = (selectedIndex, e) => {
        var changedValues = Object.assign({}, this.state.changedValues);
        changedValues[selectedIndex] = e.target.value;
        this.setState({ changedValues });
    }

    save(e) {
        //save this.state.changedValues
    }

    render() {
        return (
            <div>
                <table>
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Approve</th>
                        <th>Reject</th>
                    </tr>
                </thead>
                <tbody>
                    {this.props.approveData.map((approveData) =>
                    <tr >
                        <td>{approveData.signoffId}</td>
                        <td>
                            <div class="radio">
                                <input 
                                type="radio" 
                                value={"approve" + approveData.signoffId} 
                                name={"radio" + approveData.signoffId} 
                                onChange={this.onChange.bind(this, approveData.signoffId)} />
                            </div>
                        </td>
                        <td>
                            <div class="radio">
                                <input 
                                type="radio" 
                                value={"reject" + approveData.signoffId} 
                                name={"radio" + approveData.signoffId} 
                                onChange={this.onChange.bind(this, approveData.signoffId)} />
                            </div>
                        </td>
                    </tr>
                )}
                </tbody>
            </table>
            <Button  onClick={this.save.bind(this)} >Save</Button>
            </div>
        );
    }
}

export default ApproveDataList

I'm now confused on how to set the initial state of the radio buttons when I load this component from the back end.

My gut feeling was to do

... value={"approve" + approveData.signoffId}  checked={approveData.signedOff}

and

... value={"reject" + approveData.signoffId} checked={!approveData.signedOff}

But of course this won't work. I think I need to store the initial values in State and use that but not sure how to do this as I'm new to React and haven't found a specific solution online.

Please help!


Solution

  • I tried to replicate your issue with small code of my own.

    const dataArray = new Array(15).fill(null).map((_, index) => ({
      signoffId: index,
      signedOff: Math.random() < 0.5,
    }));
    
    export default function App() {
      return dataArray.map((obj) => (
        <div>
          <label style={{ margin: '1rem' }}>
            <input
              type="radio"
              value={'approve' + obj.signoffId}
              name={'radio' + obj.signoffId}
              defaultChecked={obj.signedOff}
              onChange={onChange.bind(this, obj.signoffId)}
            />
            Approve {obj.signoffId}
          </label>
          <label style={{ margin: '1rem' }}>
            <input
              type="radio"
              value={'reject' + obj.signoffId}
              name={'radio' + obj.signoffId}
              defaultChecked={!obj.signedOff}
              onChange={onChange.bind(this, obj.signoffId)}
            />
            Reject {obj.signoffId}
          </label>
        </div>
      ));
    
      function onChange(selectedIndex: number, e: React.BaseSyntheticEvent) {
        console.log(selectedIndex, e.target.value);
      }
    }
    

    I used functional React component but the workings should be same.

    you need to set defaultChecked prop on your radio button for initial state. If you want to set checked prop then you need to change signedOff property of respective object in onChange handler.