React: несколько строк таблицы в массиве.карта во время рендеринга
У меня есть эта проблема. Я хочу замкнуть массив и отобразить значения в виде таблицы, где каждый элемент является строкой в таблице. Пока никаких проблем. Но в зависимости от значения в каждом элементе я хочу показать дополнительную строку с большим количеством значений для каждого элемента массива. У меня есть такой код:
<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>
Моя проблема в том, что я получаю:
Предупреждение: validateDOMNesting(...): Текстовые узлы не могут отображаться как дочерние элементы
.
И
Предупреждение: validateDOMNesting(...): не может появиться как дитя
Когда я использую вышеприведенный подход. Удаление div дает мне
Syntax error, который я уже знал, но все равно пытался.
У кого-нибудь есть идея, как это решить?
3 ответов:
Ты делаешь
{item.mobile_open && <tr className="test-td"> <td>...</td> </tr> }, который выводит false как
<tr>false</tr>, Если mobile_open-false.Попробуйте
{item.mobile_open ? (<tr className="test-td"> <td>...</td> </tr>) : null }Что касается предупреждения div, рассмотрите возможность использования фрагментов React 16
Использование синтаксиса фрагмента 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>Но я предпочитаю самый последний синтаксис фрагмента React 16.2
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>Подробнее о фрагментах здесь
В React16 Теперь вы можете вернуть массив компонентов, позволяющий удалить
<div />.Код будет выглядеть примерно так:
<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>
Этим все сказано:
<div> cannot appear as a child of <tbody>В
myList.map(f),fдолжен возвращать ровно один<tr>каждый раз, когда он вызывается. Таким образом, вы можете предварительно обработатьmyList, чтобы содержать элементы JSON, которые затем могут быть отрисованы по вашему желанию.Однако, вероятно, лучше вывести одну строку для каждого элемента данных, который у вас есть, и отобразить дополнительную информацию по-другому. Может быть, вставить
divвнутрь<td>, Когда вы нажимаете значок стрелки?
Comments