web-dev-qa-db-fra.com

React: plusieurs lignes de tableau dans array.map pendant le rendu

J'ai ce problème. Je veux boucler un tableau et afficher les valeurs sous forme de tableau, chaque élément étant une ligne du tableau. Jusqu'à présent, pas de problèmes. Mais en fonction d'une valeur dans chaque élément, je souhaite afficher une ligne supplémentaire avec davantage de valeurs pour chaque élément du tableau. J'ai ce code:

<tbody>
  {myList.map((item, i) => {
    return (
      <div>
        <tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
          <td className="toggler">
            {item.mobile_open && <ArrowUp />}
            {!item.mobile_open && <ArrowDown />}
          </td>
          <td>{item.elem_one}</td>
          <td>{item.elem_two}</td>
          <td>{item.elem_three}</td>
        </tr>
        {item.mobile_open &&
          <tr className="test-td">
            <td>...</td>
          </tr>
        }
      </div>
    );
  })}
</tbody>

Mon problème est que je reçois:

Avertissement: validateDOMNesting (...): les nœuds de texte ne peuvent pas apparaître en tant qu'enfant de <tr>.

et

Avertissement: validateDOMNesting (...): <div> ne peut pas apparaître en tant qu'enfant de <tbody>

Quand j'essaye l'approche ci-dessus. Supprimer la div me donne Syntax error que je connaissais déjà mais que je tentais quand même.

Quelqu'un a-t-il une idée de la façon de résoudre ce problème?

3
BluePrint

Tu fais

{item.mobile_open &&
          <tr className="test-td">
            <td>...</td>
          </tr>
        }

qui imprime false like <tr>false</tr> si mobile_open est false.

essayer

{item.mobile_open ?
              (<tr className="test-td">
                <td>...</td>
              </tr>) : null
            }

En ce qui concerne l'avertissement div, envisagez d'utiliser React 16 Fragments.

en utilisant la syntaxe de fragment React 16.0

<tbody>
  {myList.map((item, i) => {
    return [
        <tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
          <td className="toggler">
            {item.mobile_open && <ArrowUp />}
            {!item.mobile_open && <ArrowDown />}
          </td>
          <td>{item.elem_one}</td>
          <td>{item.elem_two}</td>
          <td>{item.elem_three}</td>
        </tr>,
        {item.mobile_open &&
          <tr className="test-td">
            <td>...</td>
          </tr>
        }

    ];
  })}
</tbody>

Mais je préfère la syntaxe la plus récente de React 16.2 Fragment

import React, { Fragment } from "react";

<tbody>
      {myList.map((item, i) => {
        return (
          <Fragment>
            <tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
              <td className="toggler">
                {item.mobile_open && <ArrowUp />}
                {!item.mobile_open && <ArrowDown />}
              </td>
              <td>{item.elem_one}</td>
              <td>{item.elem_two}</td>
              <td>{item.elem_three}</td>
            </tr>
            {item.mobile_open &&
              <tr className="test-td">
                <td>...</td>
              </tr>
            }
          </Fragment>
        );
      })}
    </tbody>

Plus sur fragments ici

5
Lokuzt

Dans React16 , vous pouvez maintenant renvoyer un tableau de composants vous permettant de supprimer le <div />

Le code ressemblerait à quelque chose comme:

 <tbody>
      {myList.map((item, i) => {
        return [
            <tr key={i} onClick={toggleMobileOpen.bind(this, i)}>
              <td className="toggler">
                {item.mobile_open && <ArrowUp />}
                {!item.mobile_open && <ArrowDown />}
              </td>
              <td>{item.elem_one}</td>
              <td>{item.elem_two}</td>
              <td>{item.elem_three}</td>
            </tr>,

            //This inline conditional makes it weird but this works
            ...[item.mobile_open &&
              <tr className="test-td">
                <td>...</td>
              </tr>
            ]
        ];
      })}
    </tbody>
1
Stuart Casarotto

Cela dit tout: <div> cannot appear as a child of <tbody>

Dans myList.map(f), f devrait renvoyer exactement un <tr> à chaque appel. Vous pouvez donc prétraiter myList afin de contenir des éléments JSON pouvant être restitués à votre guise.

Cependant, il est probablement préférable de générer une ligne pour chaque donnée élémentaire et d'afficher les informations supplémentaires de manière différente. Peut-être insérer une div dans le <td> lorsque vous cliquez sur votre icône de flèche?

0
mb21