От автора: без операторов if в JSX, как вы управляете потоком приложения? Давайте рассмотрим, как отображать или НЕ отображать элементы в React.
Вы не можете вставлять оператор if в JSX. Итак, как вы контролируете, что отображается? Управление потоком через приложение имеет фундаментальное значение для программирования, и для React это ничем не отличается. В этой статье мы собираемся ответить на вопрос: как мне отобразить или скрыть что-то в React?
Я начал мозговой штурм, как по-разному отображать и скрывать вещи в React, и оказывается, что существует больше способов, чем вы думаете! Мы расскажем о плюсах и минусах каждого подхода и о том, как вы можете проверить наличие элемента с помощью библиотеки React Testing.
Полный исходный код можно найти здесь.
Возвращение Null
В современном React компонент — это не что иное, как функция, задачей которой является возвращение значения, которое должно быть отображено. Как и обычные функции, функциональные компоненты могут иметь несколько возвращаемых значений. Если то, что предоставляет компонент, представляет собой ситуацию «все или ничего», самый простой способ контролировать, отображается ли элемент, состоит в том, чтобы вообще не возвращать JSX, а вместо этого вернуть null.
Поскольку оператор if не встроен в JSX, а является частью обычной JavaScript-функции, вы можете использовать любую конструкцию JS, которая вам нравится. В этом примере, если продукт недоступен, мы просто возвращаем null.
const AddToCart = ({ available }) => { if (!available) return null; return ( <div className="full tr"> <button className="product--cart-button">Add to Cart</button> </div> ); };
Троичный оператор
Когда вам нужно контролировать, отображается один элемент или другой, или даже вообще ничего (null), вы можете использовать троичный оператор, встроенный в JSX.
В этом случае, если товаров не осталось, мы отобразим «Sold Out»; в противном случае мы будем отображать количество оставшихся товаров.
<div className="half"> <p>{description}</p> {remaining === 0 ? ( <span className="product-sold-out">Sold Out</span> ) : ( <span className="product-remaining">{remaining} remaining</span> )} </div>
Ярлык
Если вы хотите отобразить что-то только в том случае, если значение равно true, а, если результат false, ничего не должно отображаться, то лучше использовать ярлык, вместо null в части false троичного оператора. Это включает в себя использование условного оператора внутри JSX, который выглядит следующим образом checkIfTrue && <span>display if true</span>. Потому что, если операторы, использующие операнды &&, останавливаются, когда находят первое значение, которое оценивается как ложное, они не достигнут правой части (JSX), если левая часть уравнения оценивается как ложная.
Давайте посмотрим на это в действии! Мы будем отображать остальную часть названия продукта, только если у для него есть, что отображать:
<h2> <span className="product--title__large">{nameFirst}</span> {nameRest.length > 0 && ( <span className="product--title__small">{nameRest.join(" ")}</span> )} </h2>
Я должен отметить, что это вызывает проблемы в React Native, он не знает, как обрабатывать false во время вывода, и в итоге вызывает ошибку. В React Native вы должны использовать троичный оператор с возвращением null в случае false:
<h2> <span className="product--title__large">{nameFirst}</span> {nameRest.length > 0 ? ( <span className="product--title__small">{nameRest.join(" ")}</span> ) : null} </h2>
Использование свойства стиля
До этого момента мы выбирали между отображением и не отображением элемента. Что, если мы хотим отобразить элемент, но он должен быть невидимым? На данный момент у нас есть несколько вариантов. Первый — это непосредственное изменение HTML-свойства элемента style, установка атрибутов CSS, таких как display и opacity. В этом коротком примере мы устанавливаем для свойства display значения block или none, в зависимости от значения, содержащегося в showInfo. Еще раз, троичный оператор используется внутри встроенного JSX для управления потоком приложения.
<div style={{ display: showInfo ? "block" : "none" }}>info</div>
Модификация CSS-классов
По тому же принципу, что и изменение атрибутов style, мы можем изменить у элемента класс, что дает нам возможность контролировать display и opacity элемента или даже убирать его в сторону, как меню гамбургера, когда оно находится в закрытом состоянии.
В приведенном ниже примере элемент nav находится с левой стороны экрана left: -200px, но когда к элементу nav добавляется класс open, он переводится к left: 0px и внезапно снова становится видимым.
nav { position: fixed; left: -200px; width: 200px; padding: 1rem; transition: 0.3s all ease; z-index: 1000; height: 100vh; background: #cfd8dc; } nav.open { left: 0px; }
Мы можем переключать этот класс CSS, используя состояние, которое переключается внутри onClick кнопки (гамбургер), выбирая добавить класс или нет с помощью троичного условия className={open ? «open» : null}.
const Nav = () => { const [open, setOpen] = React.useState(false); return ( <nav className={open ? "open" : null}> <button onClick={() => { setOpen(!open); }} > hamburger </button> <ul>{/* elements */}</ul> </nav> ); };
Анимация видимости с помощью react-spring
Вместо того чтобы самим манипулировать классами и атрибутами стиля, мы можем обратиться к сторонней библиотеке, которая сделает это за нас. В этом случае мы используем react-spring, которая может переключать любой числовой атрибут CSS, используя свойства, основанные на физике, такие как mass, tension, и friction. Если это не совсем очевидно для вас (как, разумеется, в свое время было и для меня!), есть удобный визуализатор, который поможет вам правильно настроить параметры.
import { useSpring, animated } from "react-spring"; const SpringIn = ({ children }) => { const props = useSpring({ opacity: 1, from: { opacity: 0 }, config: { mass: 10, tension: 10, friction: 10 } }); return <animated.div style={props}>{children}</animated.div>; };
Просто оберните в пользовательский компонентом SpringIn любое содержимое — <SpringIn><div>any content</div></SpringIn> — и вы сможете задать для этого компонента анимацию react-spring.
Проверка существования с помощью библиотеки React Testing
Тестирование должно быть важной частью вашего процесса разработки React, и с помощью React Testing Library мы можем проверить наличие или отсутствие визуализируемого элемента.
В первом примере используется getByText, чтобы найти элемент, и мы ожидаем toBeInTheDocument. Тогда как во втором примере используется queryByText, чтобы проверить toBeNull. Мы переключились с getByText на queryByText, потому что getByText вызовем ошибку, если не сможем найти элемент, но во втором примере это именно то, что мы ожидаем найти!
import React from "react"; import { render, fireEvent } from "@testing-library/react"; import { AddToCart, Nav } from "./App"; test("renders cart button when available", () => { const { getByText } = render(<AddToCart available={true} />); expect(getByText(/cart/i)).toBeInTheDocument(); }); test("hides cart button when not available", () => { const { queryByText } = render(<AddToCart available={false} />); expect(queryByText(/cart/i)).toBeNull(); });
Проверка классов с помощью React Testing Library
Мы также можем использовать React Testing Library, чтобы проверить, имеет ли элемент определенный класс CSS или нет. В приведенном ниже примере nav изначально скрыт, что означает, что у него нет класса open, но после переключения состояния мы можем видеть, что у него есть класс open.
test("adds class to nav when toggled", () => { const { getByTestId } = render(<Nav />); const navElement = getByTestId("nav"); expect(navElement).not.toHaveClass("open"); fireEvent.click(getByTestId("hamburger")); expect(navElement).toHaveClass("open"); });
Заключение
В этой статье мы рассмотрели шесть различных способов отобразить или скрыть элемент в React. Иногда мы хотим, чтобы он совсем не отображался, а иногда нам нужно, чтобы он отображался, но был невидим. Для этого мы использовали атрибуты стиля и классы CSS. Наконец, мы использовали React Testing Library, чтобы убедиться, что определенный элемент был правильно отображен или не отображен.
Автор: Leigh Halliday
Источник: https://www.telerik.com
Редакция: Команда webformyself.