【问题标题】:How to handle multiple radio button groups in one component in reactjs?reactjs 如何处理一个组件中的多个单选按钮组?
【发布时间】:2018-06-09 09:49:57
【问题描述】:

我正在尝试在单击发送按钮时从多个单选按钮组中发送选定单选按钮 ID 的列表,

我的问题: 我从后端获得选中的单选按钮,然后我应该能够更改单选按钮并发送回后端。但是当我尝试更改单选按钮时它不起作用。

我不明白的地方: 如何处理 on change 函数,通常在 change 时我们可以更改状态,但要在加载时更改状态,我们应该抓住值单选按钮。最后我被击中了,不知道如何前进。

这是线框图和代码sn-p:

function CardsList(props) {
  const cards = props.cards;
  return (
    <div>
      {cards.map((card, idx) => (
       <div>
         {card.cardName}
          {
            card.options.map((lo,idx) => (
              <li key={idx}>
              <input
                 className="default"
                 type="radio"
                 name={card.cardName}
                 checked={lo.selected}
             />))
          }
         <div>
       ))}
   </div>
  );
}
//array of cards coming from the backend
const cards = [
{cardName:'card1',options:[{radioName:'card1-radio1',selected:'true'},
                          {radioName:'card1-radio2',selected:'false'}]},
  {cardName:'card2',options:[{radioName:'card2-radio1',selected:'true'},
                          {radioName:'card2-radio2',selected:'false'}]}
];
ReactDOM.render(
  <CardsList cards={cards} />,
  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>

【问题讨论】:

    标签: javascript html reactjs ecmascript-6


    【解决方案1】:

    您可以将对象用作将组名作为键保存的查找表。
    在每次更改时,您都需要找到具有相关选项的相关组并相应地设置新状态。

    重要! - 这里需要注意的一件事是,我将 selected 属性的类型从 String 更改为 Boolean。这将让我处理这样的条件:

    <input checked={option.selected} />
    

    如果您无法将其更改为Boolean,那么您将需要像这样处理这种情况:

    <input checked={option.selected === 'true'} />
    

    这是一个运行示例:

    //array of cards coming from the backend
    const data = [
      {
        cardName: 'card1', options: [{ radioName: 'card1-radio1', selected: true },
        { radioName: 'card1-radio2', selected: false }]
      },
      {
        cardName: 'card2', options: [{ radioName: 'card2-radio1', selected: true },
        { radioName: 'card2-radio2', selected: false }]
      }
    ];
    
    
    class CardsList extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          cards: []
        };
      }
    
      componentDidMount() {
        setTimeout(() => {
          // mimic an async server call
          this.setState({ cards: data });
        }, 1000);
      }
    
      onInputChange = ({ target }) => {
        const { cards } = this.state;
        const nexState = cards.map(card => {
          if (card.cardName !== target.name) return card;
          return {
            ...card,
            options: card.options.map(opt => {
              const checked = opt.radioName === target.value;
              return {
                ...opt,
                selected: checked
              }
            })
          }
        });
        this.setState({ cards: nexState })
      }
    
      onSubmit = () => { console.log(this.state.cards) };
    
      render() {
        const { cards } = this.state;
        return (
          <div>
            {
              cards.length < 1 ? "Loading..." :
                <div>
                  {cards.map((card, idx) => (
                    <ul>
                      {card.cardName}
                      {
                        card.options.map((lo, idx) => {
                          return <input
                            key={idx}
                            type="radio"
                            name={card.cardName}
                            value={lo.radioName}
                            checked={!!lo.selected}
                            onChange={this.onInputChange}
                          />
    
                        })
                      }
                    </ul>
                  ))
                  }
                  < button onClick={this.onSubmit}>Print Cards</button>
                </div>
            }
    
          </div>
        );
      }
    }
    
    ReactDOM.render(<CardsList />, 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>

    【讨论】:

      【解决方案2】:

      您无法更改它们的原因是您在此处设置的当前检查状态:

      <input
        className="default"
        type="radio"
        name={card.cardName}
        checked={lo.selected}
      />
      

      我用于这个确切场景的一种方法是将组件的状态(来自服务器)存储在我的组件状态 (this.state) 中,将状态传递给元素:checked={this.state.isChecked},并更新元素的状态 @987654324 @。

      例子:

      class CardsList extends Component {
        constructor(props){
          super(props);
          this.state = {isChecked: false};
          this.inputOnClick = this.inputOnClick.bind(this);
        }
        //fetch data from server
        fetchData(){
          fetch('/api')
            .then(res => res.json())
            //this will be our initial state
            .then(res => this.setState(res))
        }
        componentDidMount(){
          this.fetchData();
        }
        //change radio button state on click
        inputOnClick(e){
          e.preventDefault();
          //invert state value
          this.setState((prevState, props) => {isChecked: !prevState.isChecked});
        }
        render(){
          return (
            <input
              type="radio"
              checked={this.state.isChecked}
              onClick={this.inputOnClick}
             />
            )
         }
      }
      

      这个答案可能适用于单个单选按钮组,但我面临 多个单选按钮中的多个单选按钮的问题 groups.如果你看到卡片阵列,它怎么知道哪个收音机 它所属的按钮组。

      我们可以根据单选按钮的名称修改状态。

      让我们将所有卡片保存在组件的状态中。我知道卡片是从服务器检索的,并将使用setState 保存,但我这样写是为了视觉目的。

      this.state = {cards: [
        { cardName:'card1',
        options:[
          {radioName:'card1-radio1',selected:true},
          {radioName:'card1-radio2',selected:false}
         ]
        },
        { cardName:'card2',
          options:[
            {radioName:'card2-radio1',selected:true},
            {radioName:'card2-radio2',selected:false}
           ]
          }
      ]}
      

      现在,当我们单击单选按钮时,我们将使用该单选按钮的名称来更新需要更新的状态。由于 React 状态需要是不可变的,我们将创建状态的深层副本,对其进行修改,然后用它设置状态。

      inputOnClick(e){
        e.preventDefault();
        var thisRadioBtn = e.target.name;
        //make a deep copy of the state
        const stateCopy = JSON.parse(JSON.stringify(this.state.cards));
        //go through state copy and update it
        stateCopy.forEach(card => {
          card.options.forEach(option => {
            if(option.radioName === thisRadioBtn){
              //invert value
              //make sure the values are booleans
              option.selected = !option.selected;
            }
          });
        });
        //update the components state
        this.setState({cards: stateCopy});
      }
      

      【讨论】:

      • 这个答案可能适用于单个单选按钮组,但我面临多个单选按钮组中的多个单选按钮的问题。如果您看到卡片数组,它如何知道哪个单选按钮组它属于。
      • 如果我们有一个动态的状态,我们不知道从后端会得到多少张卡片?我正在尝试结束。一旦我得到完美的,我可能会发布。
      • @user8208248 只要您将获取的数据保存到您的状态,就可以了。
      猜你喜欢
      • 2019-01-26
      • 2020-01-29
      • 2020-06-26
      • 2013-06-15
      • 2016-06-12
      • 2018-11-16
      • 1970-01-01
      • 2012-08-28
      • 2019-10-04
      相关资源
      最近更新 更多