В этой части «Найди ошибку» компонент ToDoList
, принимает массив элементов и отображает их в виде списка. Однако в коде есть небольшая ошибка:
import React from "react";
const ToDoList = ({ items }) => {
return (
<div>
<ul>
{items.length && items.map(item => <li key={item.id}>{item.text}</li>)}
</ul>
</div>
);
};
const App = () => {
return (
<div>
<h2>Сегодня:</h2>
<ToDoList
items={[
{ id: 1, text: "Полить цветы" },
{ id: 2, text: "Помыть машину" },
{ id: 3, text: "Выкинуть мусор" },
]}
/>
<h2>Завтра:</h2>
<ToDoList items={[]} />
</div>
);
};
export default App;
Решение
Если вы запустите код, вы заметите, что список дел на завтра отображает 0.
Это связано с тем, как JavaScript обрабатывает оператор &&
. В React &&
обычно используется для условного рендеринга, если левая часть оператора &&
является ложной, тогда оператор &&
останавливает дальнейшее вычисление выражения.
true && "hello world" // "hello world" will be rendered
false && "hello world" // nothing will be rendered
Это работает, потому что React ничего не отобразит для логического значения false
. Однако проблема с компонентом ToDoList
заключается в том, что мы проверяем items.length
, который возвращает 0
, если элементов нет, что React отобразит как допустимый фрагмент JSX.
Как это исправить?
Самое простое решение — всегда использовать тернарный оператор при условном рендеринге в React:
import React from "react";
const ToDoList = ({ items }) => {
return (
<div>
<ul>
{items.length
? items.map((item) => <li key={item.id}>{item.text}</li>)
: null}
</ul>
</div>
);
};
const Apps = () => {
return (
<div>
<h2>Today:</h2>
<ToDoList
items={[
{ id: 1, text: "Полить цветы" },
{ id: 2, text: "Помыть машину" },
{ id: 3, text: "Вынести мусор" }
]}
/>
<h2>Tomorrow:</h2>
<ToDoList items={[]} />
</div>
);
};
export default App;
Таким образом, вы явно указываете React, что отображать, если левая часть тернарной операции ложна — в этом случае, если элементов нет, мы хотим отобразить null
. Как и ожидалось, для завтрашнего списка дел ничего не отображается.
Это хороший шаблон, поскольку он заставляет вас более думать о ложных случаях в вашем коде. Например, в этом случае было бы неплохо отобразить некоторый текст, сообщающий пользователю, что список дел пуст.
***
В будущем следует обратить внимание на то, что может помочь с условным рендерингом, это выражение do
, которое позволят нам делать что-то вроде этого:
return (
<nav>
<Home />
{
do {
if (loggedIn) {
<LogoutButton />
} else {
<LoginButton />
}
}
}
</nav>
)
В настоящее время do
находится на стадии предложения, но, на мой взгляд, этот способ понятнее и проще в использовании, чем тернарные условия, особенно когда есть несколько вложенных условий.
Спасибо за внимание!
Найдите ошибку: Функциональное Карри