2
votes

Comment enregistrer l'entrée saisie par l'utilisateur dans un état qui est un tableau dans React

L'idée est de prendre les entrées des utilisateurs dans un formulaire et d'afficher leur entrée dans un objet JSON. Dans l'état, j'ai un tableau et à l'intérieur un autre tableau.

Mon Form.js ressemble à ceci,

"typeA": ["field1 value", "field2 value"],
"typeB": ["field3 value", "field4 value"]}
render(){
        return(
            <div class="classform">
            <form >
                <label>
                    Field1:
                    <br/>
                    <input type="text"
                    name="typeA"
                    placeholder="Type A"
   //store it as the first element of the type A
                    value={this.state.groups.typeA[0]} 
                    onChange={this.change.bind(this)}
                 />
  //other fields with the same code

Par la suite, Field2 sera stocké comme deuxième élément de type A Ensuite, Field3 et Field4 seront stockés en tant que 2 du tableau de type B

Je m'attends à ce que le code me donne une sortie comme:

state= {
    groups:[{
      typeA:[{}],
      typeB:[{}]
    }],
    credentials: false
    };

    change = e =>{
        this.setState({[e.target.name]: e.target.value})
    };

    handleSubmit(event) {
        event.preventDefault();
        this.setState({
          credentials: true 
        });
      }

Je suis un débutant avec React et je ne suis pas en mesure de stocker les valeurs de champ dans l'état qui est un tableau.


0 commentaires

3 Réponses :


3
votes

Par souci de simplicité, je recommanderai la solution ci-dessous, Au lieu d'avoir un tableau imbriqué dans l'état, vous pouvez gérer les valeurs d'entrée dans les différentes variables d'état et au moment de la soumission, les changer pour la sortie souhaitée.

render(){
  return(
    <div class="classform">
      <form >
        <label>
          Field1:
          <br/>
          <input type="text"
            name="field1"
            placeholder="Type A"
            value={this.state.field1}
            onChange={this.change}
          />
        </label>
        <label>
          Field2:
          <br/>
          <input type="text"
            name="field2"
            placeholder="Type A"
            value={this.state.field2}
            onChange={this.change}
          />
        </label>
state = {
  field1: '',
  field2: '',
  field3: '',
  field4: '',
}
change = e => {
  this.setState({[e.target.name]: e.target.value})
};

handleSubmit(event) {
  event.preventDefault();
  const { field1, field2, field3, field4 } = this.state;
  // This is your output
  const output = [{typeA: [field1, field2], typeB: [field2, field3]}];
  this.setState({
    credentials: true 
  });
}


0 commentaires

2
votes

essayez ceci:

import React, { Component } from "react";

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      groups: [
        {
          typeA: [{}],
          typeB: [{}]
        }
      ],
      credentials: false
    };
  }

  change = (e, key) => {
    let { groups } = this.state;

    let myVal = groups[0][e.target.name];
    // or if you want to add value in an object likr [{value: 'abcd'}]
    myVal[0][key] = e.target.value;
    groups[0][e.target.name] = myVal;
    console.log("TCL: App -> groups", groups);
    this.setState({ groups });
  };

  render() {
    return (
      <div>
        <input
          type="text"
          name="typeA"
          placeholder="Type A"
          value={this.state.groups[0].typeA[0].value2}
          onChange={e => this.change(e, "value2")}
        />
        <input
          type="text"
          name="typeA"
          placeholder="Type A2"
          value={this.state.groups[0].typeA[0].value}
          onChange={e => this.change(e, "value")}
        />
        <br />
        <input
          type="text"
          name="typeB"
          placeholder="Type b"
          value={this.state.groups[0].typeB[0].value}
          onChange={e => this.change(e, "value")}
        />
      </div>
    );
  }
}



11 commentaires

Cela me donne une erreur TypeError: Impossible d'obtenir la propriété '0' d'une référence non définie ou nulle. Dois-je également modifier le "nom" dans la balise d'entrée


Donnant toujours la même erreur. J'ai aussi essayé myVal = groups [e.target.name] [0] (pour qu'il prenne le nom = "typeA" puis insère dans [0] index). Pensez-vous que je devrais utiliser une carte pour attribuer les valeurs du tableau?


veuillez réessayer!


Nan! ne fonctionne toujours pas :( Il n'entre même pas dans le retour. Donne la même erreur "TypeError: Impossible d'obtenir la propriété '0' d'une référence non définie ou nulle"


Hou la la! Ça a marché! Juste une chose, pour les colonnes suivantes, comme col2 (deuxième élément pour le tableau typeA) et col 3 et col 4 (2 éléments dans le tableau typeB). Comment changer les valeurs? Supposons que j'enveloppe le

dans la fonction de carte, mais comment changer l'index des valeurs dans la fonction de chnage


Pour la zone de saisie suivante, il remplace la valeur précédente. Cela ne crée pas une autre valeur pour la prochaine entrée


maintenant revérifiez! son travail pour moi! Je pense que vous oubliez de changer la valeur ( typeA || typeB ) dans l'attribut value!


Désolé, pour le malentendu, cette partie fonctionne. Mais si j'ajoute un autre champ de typeA. Ensuite, il écrase la valeur. Pour y parvenir, "typeA": ["valeur champ1", "valeur champ2"]. J'ai besoin d'un champ supplémentaire pour le typeA. mais il ne prend qu'une seule valeur et n'ajoute pas la nouvelle valeur au tableau


pourquoi cela me donne-t-il cette erreur: "Impossible de lire la propriété 'value' de undefined" lorsque j'essaye d'exécuter "value = {this.state.filters [0] .company_meta [1] .value}". Idéalement, il devrait l'enregistrer dans l'élément suivant du tableau.


maintenant revérifiez! maintenant, cela résoudra votre problème de remplacement sur le terrain!


et si vous voulez obtenir une valeur, vous devez écrire value = {this.state.groups [0] .typeA [0] .value} car il n'y a pas de deuxième index, ce sont des tableaux! donc le 0 ne sera disponible que!



1
votes

Attribuez à chaque entrée un attribut personnalisé, par exemple data-group = "typeA" . Dans votre fonction on change, récupérez cette valeur et ajoutez les valeurs au tableau correct.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

function formatState(json) {
  if (typeof json != 'string') {
       json = JSON.stringify(json, undefined, 2);
  }
  json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match) => match);
}

const Credentials = ({ value }) => {
  return <pre>{formatState(value)}</pre>;
};

class App extends React.Component {
  state = {
    groups: [
      {
        typeA: [],
        typeB: []
      }
    ],
    credentials: false
  };

  handleSubmit = event => {
    event.preventDefault();

    this.setState({
      credentials: true // display Credentials  component
    });
  };

  // get the current input index in the array typeA | typeB
  findFieldIndex = (array, name) => {
    return array.findIndex(item => item[name] !== undefined);
  };

    change = e => {

      // create a copy of  this.state.groups
      const copyGroups = JSON.parse(JSON.stringify(this.state.groups));

      // get data-group value
      const group = event.target.dataset.group;
      
      if (!copyGroups[0][group]) {
        copyGroups[0][group] = []; // add new type
      }
      
      const groups = copyGroups[0][group];
      const index = this.findFieldIndex(groups, e.target.name);

      if (index < 0) {
        // if input doesn't exists add to the array
        copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
      } else {
        // update the value
        copyGroups[0][group][index][e.target.name] = e.target.value;
      }

      this.setState({ groups: copyGroups });
    };
    
 removeKey = (key) => {
    const temp = {...this.state};
    delete temp[key];
    return temp;
 }

  render() {
    return (
      <div>
        <input
          type="text"
          name="col1"
          placeholder="Type A"
          data-group="typeA"
          onChange={e => this.change(e)}
        />

        <input
          type="text"
          name="col2"
          placeholder="Type A"
          data-group="typeA"
          onChange={e => this.change(e)}
        />

        <input
          type="text"
          name="col2"
          placeholder="Type B"
          data-group="typeB"
          onChange={e => this.change(e)}
        />
        
        <input
          type="text"
          name="typec"
          placeholder="Type C | New Type"
          data-group="typeC"
          onChange={e => this.change(e)}
        />
        
        <input
          type="text"
          name="typed"
          placeholder="Type D | New Type"
          data-group="typeD"
          onChange={e => this.change(e)}
        />

        <button onClick={this.handleSubmit}>Submit</button>
        {this.state.credentials && (
          <Credentials value={JSON.stringify(this.removeKey('credentials'), undefined, 2)} />
        )}
      </div>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
</script>

Dans votre poignée de modification, récupérez l'attribut personnalisé et utilisez-le pour ajouter la valeur au tableau correct.

pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }

change = e => {

  // create a copy of  this.state.groups
  const copyGroups = JSON.parse(JSON.stringify(this.state.groups));

  // get data-group value
  const group = event.target.dataset.group;

  if (!copyGroups[0][group]) {
    copyGroups[0][group] = []; // add type if it doesn't exists
  }

  const groups = copyGroups[0][group];
  const index = this.findFieldIndex(groups, e.target.name);

  if (index < 0) {
    // if input doesn't exists add to the array
    copyGroups[0][group] = [...groups, { [e.target.name]: e.target.value }];
  } else {
    // else update the value
    copyGroups[0][group][index][e.target.name] = e.target.value;
  }

  this.setState({ groups: copyGroups });
};
<input
  type="text"
  name="col2"
  placeholder="Type A"
  data-group="typeA" // add custom attribute typeA | typeB etc.
  onChange={e => this.change(e)}
/>


9 commentaires

OMG! Cool! Merci! Pouvez-vous me dire comment imprimer l'objet JSON sans imprimer les informations d'identification: true? Je viens de l'utiliser pour imprimer l'objet JSON


Utilisez delete stackoverflow.com/questions/3455405/…


D'accord, je vois! Merci


Oui, j'ai compris! Merci de votre aide


Salut Junis, j'avais une question qui n'est qu'une extension de cette question. Je veux savoir s'il existe un moyen de stocker les valeurs d'entrée sous forme de tableau (et uniquement les valeurs). Supposons que si j'ai une date de début et une date de fin de colonne: je souhaite stocker les valeurs sous la forme d'un tableau. Donc, j'ai besoin d'une sortie comme: typeA: [[col1value1, col1value2], [startdate, enddate]]. Je sais que c'est compliqué, mais je la sortie devrait ressembler à ceci. Peu importe, même si je ne le stocke pas dans un tableau


@ user8306074 oui vous pouvez.


Pour ce faire, dois-je personnaliser la sortie JSON ou trouver un moyen de stocker les valeurs d'entrée dans un tableau?


Pouvez-vous me dire une chose de plus, si possible, dans cet exemple, vous stockez toutes les valeurs de champ d'entrée dans un tableau; comme typeA et typeB sont des tableaux, comment puis-je les convertir en liste? Je ne le veux pas sous forme de tableau Je le veux sous forme de liste car cela m'aidera à atteindre la sortie souhaitée


Continuons cette discussion dans le chat .