如何在ReactJS中使用单选按钮?


203

我是ReactJS的新手,很抱歉,如果听起来不对。我有一个根据接收到的数据创建多个表行的组件。

列中的每个单元格都有一个单选复选框。因此,用户可以从现有行中选择一个site_name和一个address。选项应在页脚中显示。那就是我被困住的地方。

var SearchResult = React.createClass({
   render: function(){
       var resultRows = this.props.data.map(function(result){
           return (
               <tbody>
                    <tr>
                        <td><input type="radio" name="site_name" value={result.SITE_NAME}>{result.SITE_NAME}</input></td>
                        <td><input type="radio" name="address" value={result.ADDRESS}>{result.ADDRESS}</input></td>
                    </tr>
               </tbody>
           );
       });
       return (
           <table className="table">
               <thead>
                   <tr>
                       <th>Name</th>
                       <th>Address</th>
                   </tr>
               </thead>
                {resultRows}
               <tfoot>
                   <tr>
                       <td>chosen site name ???? </td>
                       <td>chosen address ????? </td>
                   </tr>
               </tfoot>
           </table>
       );
   }
});

在jQuery中,我可以执行一些操作,例如$("input[name=site_name]:checked").val()选择一个单选复选框类型并将其插入第一个页脚单元格。

但是肯定有一种Reactjs方式,我完全不知道吗?非常感谢


3
input元素没有内容。因此<input>content</input>没有任何意义,并且是无效的。您可能想要<label><input />content</label>
Oriol 2015年

1
单选按钮不必具有相同的名称和不同的值才能工作吗?
pgee70 '16

Answers:


209

渲染的任何更改都应通过statepropsreact doc)进行更改。

因此,在这里我注册了输入事件,然后更改了state,这将触发呈现在页脚上的渲染。

var SearchResult = React.createClass({
  getInitialState: function () {
    return {
      site: '',
      address: ''
    };
  },
  onSiteChanged: function (e) {
    this.setState({
      site: e.currentTarget.value
      });
  },

  onAddressChanged: function (e) {
    this.setState({
      address: e.currentTarget.value
      });
  },

  render: function(){
       var resultRows = this.props.data.map(function(result){
           return (
               <tbody>
                    <tr>
                        <td><input type="radio" name="site_name" 
                                   value={result.SITE_NAME} 
                                   checked={this.state.site === result.SITE_NAME} 
                                   onChange={this.onSiteChanged} />{result.SITE_NAME}</td>
                        <td><input type="radio" name="address" 
                                   value={result.ADDRESS}  
                                   checked={this.state.address === result.ADDRESS} 
                                   onChange={this.onAddressChanged} />{result.ADDRESS}</td>
                    </tr>
               </tbody>
           );
       }, this);
       return (
           <table className="table">
               <thead>
                   <tr>
                       <th>Name</th>
                       <th>Address</th>
                   </tr>
               </thead>
                {resultRows}
               <tfoot>
                   <tr>
                       <td>chosen site name {this.state.site} </td>
                       <td>chosen address {this.state.address} </td>
                   </tr>
               </tfoot>
           </table>
       );
  }
});

jsbin


3
那很有用。谢谢。我不明白的是它的}, this);下方</tbody>。这是什么,它做什么?我注意到没有代码崩溃。
侯曼

3
this是传递给上下文map功能。这是@FakeRainBrigand的编辑,很不错!没有它,你this的地图功能将涉及window,其中有不知道的东西state
ChinKang

8
this如果使用ES6箭头而不是常规函数,则不需要此技巧。例如:var resultRows = this.props.data.map((result) => { ... });我只提到它是因为React-ers通常已经在使用某种形式的转换(对于JSX),因此ES6通常很容易到达。
汤姆(Tom)

1
使用两个函数来获取单选按钮的值似乎是模棱两可和不必要的。您可能只定义了一个函数,也许onInputChange (e) {this.setState({ [e.target.name]: e.target.value }); }
xplorer1

108

这是在react js中实现单选按钮的最简单方法。

class App extends React.Component {
  
  setGender(event) {
    console.log(event.target.value);
  }
  
  render() {
    return ( 
      <div onChange={this.setGender.bind(this)}>
        <input type="radio" value="MALE" name="gender"/> Male
        <input type="radio" value="FEMALE" name="gender"/> Female
      </div>
     )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

已编辑

您可以使用箭头功能代替绑定。将上面的代码替换为

<div onChange={event => this.setGender(event)}>

要使用默认值defaultChecked,像这样

<input type="radio" value="MALE" defaultChecked name="gender"/> Male

6
相信.bind(this)每次都会创建一个新功能。这意味着当反应检查以查看虚拟DOM中是否有任何更改时,此组件将始终是不同的,并且始终需要重新呈现。
WoodenKitty '17

1
如果将每个功能作为道具传递给子组件,则每个渲染器上的新功能只会是一个问题。在这种情况下,接收道具的子组件可能会不必要地渲染。父组件会很好。
Mark McKelvy

5
对我而言,这仅适用于单击共享相同名称的每个收音机一次。例如,我有两个具有相同name道具的收音机。它们都包装在具有onChange此答案所述处理程序的div中。我单击第一个广播,事件被触发。我单击第二个收音机,将触发一个事件。但是,第三次及以后,不会触发任何事件。为什么?
Squrler '17

4
@Saahithyan我在所有收音机中都具有相同的name属性。原来,我需要将onClick处理程序放置到单选输入中,而不是onChange处理程序。做到了。
Squrler

3
我同意@Squrler -使用onChange时,该句柄仅对div下包含的每个单选按钮触发一次。使用onClick,它可以多次工作。不确定为什么将它与您的
摘要

25

根据React Docs所说

处理多个输入。 当需要处理多个受控输入元素时,可以向每个元素添加一个name属性,并让处理函数根据event.target.name的值选择要执行的操作。

例如:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  handleChange = e => {
    const { name, value } = e.target;

    this.setState({
      [name]: value
    });
  };

  render() {
    return (
      <div className="radio-buttons">
        Windows
        <input
          id="windows"
          value="windows"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Mac
        <input
          id="mac"
          value="mac"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Linux
        <input
          id="linux"
          value="linux"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

链接到示例:https : //codesandbox.io/s/6l6v9p0qkr

最初,没有选择this.state任何单选按钮,而是一个空对象,但是每当选择该单选按钮时,this.state都会获得一个带有输入名称及其值的新属性。然后轻松检查用户是否选择了任何单选按钮,例如:

const isSelected = this.state.platform ? true : false;

编辑:

在React的16.7-alpha版本中,有一个提议叫做hooks它可以让您更轻松地进行这种操作:

在下面的示例中,功能组件中有两组单选按钮。他们仍然控制着输入:

function App() {
  const [platformValue, plaftormInputProps] = useRadioButtons("platform");
  const [genderValue, genderInputProps] = useRadioButtons("gender");
  return (
    <div>
      <form>
        <fieldset>
          Windows
          <input
            value="windows"
            checked={platformValue === "windows"}
            {...plaftormInputProps}
          />
          Mac
          <input
            value="mac"
            checked={platformValue === "mac"}
            {...plaftormInputProps}
          />
          Linux
          <input
            value="linux"
            checked={platformValue === "linux"}
            {...plaftormInputProps}
          />
        </fieldset>
        <fieldset>
          Male
          <input
            value="male"
            checked={genderValue === "male"}
            {...genderInputProps}
          />
          Female
          <input
            value="female"
            checked={genderValue === "female"}
            {...genderInputProps}
          />
        </fieldset>
      </form>
    </div>
  );
}

function useRadioButtons(name) {
  const [value, setState] = useState(null);

  const handleChange = e => {
    setState(e.target.value);
  };

  const inputProps = {
    name,
    type: "radio",
    onChange: handleChange
  };

  return [value, inputProps];
}

工作示例:https//codesandbox.io/s/6l6v9p0qkr


20

使收音机组件成为哑组件,并将道具传递给父组件。

import React from "react";

const Radiocomponent = ({ value, setGender }) => ( 
  <div onChange={setGender.bind(this)}>
    <input type="radio" value="MALE" name="gender" defaultChecked={value ==="MALE"} /> Male
    <input type="radio" value="FEMALE" name="gender" defaultChecked={value ==="FEMALE"}/> Female
  </div>
);

export default Radiocomponent;

2
由于转储组件是一个纯函数,因此很容易测试。
兹·阿扎姆

7

这里只是一个想法:关于React中的无线电输入,我通常以以前答案中提到的不同方式渲染所有输入。

如果这可以帮助需要渲染大量单选按钮的任何人,请执行以下操作:

import React from "react"
import ReactDOM from "react-dom"

// This Component should obviously be a class if you want it to work ;)

const RadioInputs = (props) => {
  /*
    [[Label, associated value], ...]
  */
  
  const inputs = [["Male", "M"], ["Female", "F"], ["Other", "O"]]
  
  return (
    <div>
      {
        inputs.map(([text, value], i) => (
	  <div key={ i }>
	    <input type="radio"
              checked={ this.state.gender === value } 
	      onChange={ /* You'll need an event function here */ } 
	      value={ value } /> 
    	    { text }
          </div>
        ))
      }
    </div>
  )
}

ReactDOM.render(
  <RadioInputs />,
  document.getElementById("root")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>


1
这很棒。非常干,使事情变得美好。我会为每个选项使用一个对象,但是我想这是一个偏好问题。
nbkhope

@nbkhope如果必须重写它,我也将使用object!:)
Arnaud

检查以下行:checked={ this.state.gender === value }。功能组件没有this
亚伯拉罕·埃尔南德斯

6
import React, { Component } from "react";

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

    this.state = {
      // gender : "" , // use this one if you don't wanna any default value for gender
      gender: "male" // we are using this state to store the value of the radio button and also use to display the active radio button
    };

    this.handleRadioChange = this.handleRadioChange.bind(this);  // we require access to the state of component so we have to bind our function 
  }

  // this function is called whenever you change the radion button 
  handleRadioChange(event) {
      // set the new value of checked radion button to state using setState function which is async funtion
    this.setState({
      gender: event.target.value
    });
  }


  render() {
    return (
      <div>
        <div check>
          <input
            type="radio"
            value="male" // this is te value which will be picked up after radio button change
            checked={this.state.gender === "male"} // when this is true it show the male radio button in checked 
            onChange={this.handleRadioChange} // whenever it changes from checked to uncheck or via-versa it goes to the handleRadioChange function
          />
          <span
           style={{ marginLeft: "5px" }} // inline style in reactjs 
          >Male</span>
        </div>
        <div check>
          <input
            type="radio"
            value="female"
            checked={this.state.gender === "female"}
            onChange={this.handleRadioChange}
          />
          <span style={{ marginLeft: "5px" }}>Female</span>
        </div>
      </div>
    );
  }
}
export default RadionButtons;

1
您的代码有效,但您也应该对其
做些

注意:不要在onChange处理函数中使用preventDefault,因为它会阻止检查设置为DOM组件
AlexNikonov

2

单击单选按钮应触发以下事件:

  1. 如果只希望选择知识是本地的,则调用setState,或者
  2. 调用从上面传递过来的回调 self.props.selectionChanged(...)

在第一种情况下,更改为状态将触发重新渲染,您可以执行
<td>chosen site name {this.state.chosenSiteName} </td>

在第二种情况下,回调的源将更新内容以确保从头开始,您的SearchResult实例将在其props中设置selectedSiteName和selectedAddress。


2

为了建立在ChinKang所说的答案的基础上,我有一个更干燥的方法,在es6中,对于那些感兴趣的人:

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

    this.state = {
      selectedRadio: 'public'
    };
  }

  handleRadioChange = (event) => {
    this.setState({
      selectedRadio: event.currentTarget.value
    })
  };

  render() {
    return (
      <div className="radio-row">
        <div className="input-row">
          <input
            type="radio"
            name="public"
            value="public"
            checked={this.state.selectedRadio === 'public'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="public">Public</label>
        </div>
        <div className="input-row">
          <input
            type="radio"
            name="private"
            value="private"
            checked={this.state.selectedRadio === 'private'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="private">Private</label>
        </div>
      </div>
    )
  }
}

除了这一点将具有默认的检查值。


1

我还对收音机,复选框的实现感到困惑。我们需要的是,收听广播的更改事件,然后设置状态。我列举了性别选择的一个小例子。

/*
 * A simple React component
 */
class App extends React.Component {
  constructor(params) {
     super(params) 
     // initial gender state set from props
     this.state = {
       gender: this.props.gender
     }
     this.setGender = this.setGender.bind(this)
  }
  
  setGender(e) {
    this.setState({
      gender: e.target.value
    })
  }
  
  render() {
    const {gender} = this.state
    return  <div>
        Gender:
        <div>
          <input type="radio" checked={gender == "male"} 
onClick={this.setGender} value="male" /> Male
          <input type="radio" checked={gender == "female"} 
onClick={this.setGender} value="female"  /> Female
        </div>
        { "Select Gender: " } {gender}
      </div>;
  }
}

/*
 * Render the above component into the div#app
 */
ReactDOM.render(<App gender="male" />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>


0

引导家伙,我们这样做:


export default function RadioButton({ onChange, option }) {
    const handleChange = event => {
        onChange(event.target.value)
    }

    return (
        <>
            <div className="custom-control custom-radio">
                <input
                    type="radio"
                    id={ option.option }
                    name="customRadio"
                    className="custom-control-input"
                    onChange={ handleChange }
                    value = { option.id }
                    />
                    <label
                        className="custom-control-label"
                        htmlFor={ option.option }
                        >
                        { option.option }
                    </label>
            </div>
        </>
    )
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.