web-dev-qa-db-fra.com

Comment gérer plusieurs groupes de boutons radio dans un composant dans reactjs?

J'essaie d'envoyer la liste des ID de bouton radio sélectionnés à partir de plusieurs groupes de boutons radio en cliquant sur le bouton Envoyer,

Mon problème: Je suis en train de sélectionner le bouton radio du backend, je devrais alors pouvoir le changer et le renvoyer au backend. mais lorsque j'essaie de changer le bouton radio, cela ne fonctionne pas.

Ce que je ne comprenais pas: Comment gérer la fonction on change, normalement lors d’un changement, nous pouvons changer l’état, mais pour changer l’état à la charge, nous devons saisir les boutons radio de valeurs. Finalement, j'ai été frappé ici, ne comprenant pas comment avancer.

Voici l'extrait de filaire et de code:

 wireframe

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>
6
sravan kumar ganji

Vous pouvez utiliser un objet en tant que table de recherche contenant les noms de groupe en tant que clés.
À chaque changement, vous devrez trouver le groupe approprié avec l’option appropriée et définir le nouvel état en conséquence. 

Important! - Une chose à noter ici est que j’ai modifié le type de la propriété selected de String à Boolean. cela me permettra de gérer les conditions comme ceci:

<input checked={option.selected} />

Si vous ne pouvez pas le changer en Boolean, vous devrez gérer la condition de la manière suivante: 

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

Voici un exemple en cours d'exécution:

//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>

1
Sagiv b.g

La raison pour laquelle vous ne pouvez pas les modifier est due à leur état coché actuel que vous définissez ici:

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

Une approche que j'ai utilisée pour ce scénario exact consiste à stocker l'état du composant (à partir du serveur) dans l'état de mon composant (this.state), à transmettre l'état à l'élément: checked={this.state.isChecked} et à mettre à jour l'état de l'élément onClick.

Exemple:

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}
       />
      )
   }
}

cette réponse peut fonctionner avec un seul groupe de boutons radio, mais je rencontre un problème de avec plusieurs boutons radio avec dans plusieurs groupes de boutons radio . Si vous voyez le tableau de cartes, comment sait-il quelle radio? groupe de boutons auquel il appartient.

Nous pouvons modifier l'état en fonction du nom du bouton radio. 

Sauvegardons toutes vos cartes dans l'état de votre composant. Je sais que les cartes sont extraites du serveur et seront sauvegardées avec setState mais je l’écris comme ceci à des fins visuelles.

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

Maintenant, lorsque nous cliquons sur un bouton radio, nous allons utiliser le nom de ce bouton pour mettre à jour l'état dans lequel il doit être mis à jour. Étant donné que l'état de réaction doit être immuable, nous allons créer une copie complète de l'état, le modifier, puis définir l'état avec.

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});
}
1
Josan Iracheta