最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle multiple radio button groups in one component in reactjs? - Stack Overflow

programmeradmin5浏览0评论

I'm trying to send list of selected radio button ids from multiple radio button groups on clicking send button,

My problem: I am getting selected radio button from backend , then I should be able to change the radio button and send back to backend. but when I try to change the radio button it is not working.

What I did not understand: How to handle the on change function, normally on change we can change the state but to change the state on load we should grab the values radio buttons. Finally I got struck here, not understanding how to move forward.

Here is the wireframe and code snippet:

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 ing 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=".1.0/react.min.js"></script>
<script src=".1.0/react-dom.min.js"></script>
<div id="root"></div>

I'm trying to send list of selected radio button ids from multiple radio button groups on clicking send button,

My problem: I am getting selected radio button from backend , then I should be able to change the radio button and send back to backend. but when I try to change the radio button it is not working.

What I did not understand: How to handle the on change function, normally on change we can change the state but to change the state on load we should grab the values radio buttons. Finally I got struck here, not understanding how to move forward.

Here is the wireframe and code snippet:

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 ing 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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Share Improve this question edited Jan 8, 2018 at 15:59 JonathanDavidArndt 2,74213 gold badges39 silver badges52 bronze badges asked Dec 28, 2017 at 21:06 sravan ganjisravan ganji 5,1255 gold badges27 silver badges43 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

You can use an object as a lookup table that holds the group names as keys.
On each change you will need to find the relevant group with the relevant option and set the new state accordingly.

Important! - one thing to notice here, is that i changed the type of the selected property from a String to a Boolean. this will let me handle the conditions like this:

<input checked={option.selected} />

If you can't change it to a Boolean then you will need to handle the condition like this:

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

Here is a running example:

//array of cards ing 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: []
    };
  }

  ponentDidMount() {
    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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

The reason why you can't change them is because of their current checked state which you are setting here:

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

An approach I have used for this exact scenario is storing the ponent's state (from the server) in my ponent's state (this.state), passing the state to the element: checked={this.state.isChecked}, and updating the element's state onClick.

Example:

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))
  }
  ponentDidMount(){
    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}
       />
      )
   }
}

this answer may work with single radio button group , but i am facing problem with multiple radio buttons with in multiple radio button groups.if you see the array of cards , how does it know which radio button group it belongs to.

We can modify the state based on the radio button's name.

Let's save all of your cards in your ponent's state. I know the cards are retrieved from the server and will be saved using setState but I am writing it like this for visual purposes.

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}
     ]
    }
]}

Now when we click on a radio button, we will use that radio button's name to update the state where it needs to be updated. Since React state needs to be immutable, we will create a deep copy of the state, modify it, and then set the state with it.

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 ponents state
  this.setState({cards: stateCopy});
}

In June 2022, I'm facing a similar issue with you. My solution is just add tag <form> on both sections with no OnSubmit or action on it.

发布评论

评论列表(0)

  1. 暂无评论