Create a custom radio button using React JS

2020-03-31 04:26发布

I'm trying to create a custom radio button. The issue that i'm facing is that i'm unable to uncheck the radio button when another radio button is clicked. Currently it behaves like a checkbox.

import {React, ReactDOM} from '../../shared/lib/react';

export default class RadioButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          checkedRadioBtn: false
        };
        this.toggleRadioBtn = this.toggleRadioBtn.bind(this);
     };


    toggleRadioBtn(){
        this.setState({checkedRadioBtn: !this.state.checkedRadioBtn});
    };

    render() {
        return (
            <div className="radio-btn-group">
                <div onClick={this.toggleRadioBtn} className={this.state.checkedRadioBtn ? "radiobtn checked" : "radiobtn unchecked"} data-value={this.props.value}></div>
                <label>{this.props.text}</label>
            </div>
        );
    }
};

2条回答
Rolldiameter
2楼-- · 2020-03-31 05:05

You need to have container for group of radio buttons. That container will maintain the state for all the radio buttons and handle check/uncheck for each option. Here is the sample code for that,

import React from 'react'
import ReactDOM from 'react-dom'

class RadioBtn extends React.Component{

    constructor(props) {
        super(props);
    }

    handleClick(){
        this.props.handler(this.props.index);
    }

    render() {
        return (
            <div className="radio-btn-group" onClick={this.handleClick.bind(this)}>
                <div className={this.props.isChecked ? "radiobtn checked" : "radiobtn unchecked"} data-value={this.props.value}></div>
                <label>{this.props.text}</label>
            </div>
        );
    }
}

class RadioGrp extends React.Component{

    constructor() {
        super();
        this.state = {
          selectedIndex: null,
          selectedValue: null,
          options: ["option 0","option 1","option 2","option 3"]
        };
    }

    toggleRadioBtn(index){
        this.setState({
          selectedIndex: index,
          selectedValue: this.state.options[index],
          options: this.state.options
        });
    }

    render() {

        const { options } = this.state;

        const allOptions = options.map((option, i) => {
            return <RadioBtn key={i} isChecked={(this.state.selectedIndex == i)} text={option} value={option} index={i} handler={this.toggleRadioBtn.bind(this)} />
        });

        return (
            <div>{allOptions}</div>
        );
    }
}

var app = document.getElementById('app');

ReactDOM.render(<RadioGrp />, app);
查看更多
神经病院院长
3楼-- · 2020-03-31 05:16

Since you're using a div for a custom checkbox that doesn't behave like a normal checkbox you should be checking value against the selected value.

toggleRadioBtn(e){
    this.setState({checkedRadioBtn: e.target.value});
};

Another question that I have is that you are assuming a single checkbox here so I have to assume you have a calling component that returns multiple instances. If that is the case then you need to pass your onClick down so you can pass the value back up to the parent. Then pass the selected value back down.

This is an example that I have in my application.

var languges = this.props.languages;
    var languageToSelect = this.state.selectedLanguage;
    var handleChange = this.handleChange;
    var languageRows = Object.keys(languges).map(function(key) {
        var language = languges[key];
        return <LanguageBlock
                    key={ key }
                    language={ language }
                    languageCode={ key }
                    checked={ languageToSelect === key }
                    handleChange={ handleChange }
                />;
    });

In my use case I have multiple languages and onChange I pass the selected language back up then on rerender the selected language will be updated so the radio options will reflect the change.

handleChange: function handleChange(event) {
    this.setState({ selectedLanguage: event.target.value });
},

The handle change just sets state for the new value. The language block itself is just a simple component so no need to make it a class/component.

const LanguageBlock = ({ checked, language, languageCode, handleChange }) => {
return (
    <div className="truncification">
        <input type="radio" name="lang" id={ 'lang_' + languageCode }
            value={ languageCode } checked={ checked } onChange={ (evt) => { handleChange(evt); } } />
        <label htmlFor={ 'lang_' + languageCode }>{ language }</label>
    </div>
);
};
查看更多
登录 后发表回答