Фрагменты React і StrictMode: простейшая маркапінг і ранэйскія выяўленні багоў
Дазвольце дазнаць, як фрагменты React групаваюць элементы без дадзейшых кантэйнероў DOM, і як двойная запуск режыму StrictMode, прызначанага толькі для разработкі, адкрывае нечыстыя процесы выкарыстання элементаў і ўплывы на ўтварэнне інтерфейса.
Два фічы React, які ніколі не адрабатваюць нічога на экране, пры тым утвараюць майже кожную дрэва компанентаў: Fragments і StrictMode. Fragments заходзяцься пра тое, каб ваш DOM быў вільны ад элементаў-обгортакоў, якія існуюць толькі для задоволення патрабавакаў JSX, тады як StrictMode спецыяльна стварае напругу ў вашых компанентах пад час розработы, каб нечыстая логіка стала видна раней, чым яе побачуць корыстнікі.
Чаму JSX патрабуе аднае коранявай точкі
JSX кампілюе кожны тэг у вызыв функцыі, таму два сяброўскія тэгі, якія вяртаюцца разам, ёсць двумя значэннямі, калі ж патрабуецца толькі адна. Гэта не дазволяе кампіляцыі:
return (
<h1>Hello</h1>
<p>Welcome</p>
);
Традыцыйны спосаб рашэння быў у тым, каб загорнуць сяброўскія тэгі ў div:
return (
<div>
<h1>Hello</h1>
<p>Welcome</p>
</div>
);
Дадатковы вузол мае своія наследкі: ён паглыбляе структуру DOM, наражае на проблемы лейяуты типу flex або grid, якія патрабуюць прымітных дзецячых элементаў, ускладнюе выбіранне селектараў і можа прызвесці да неваліднага або менш доступнага HTML.
Групаванне без обгортака
Fragment агрупавае дзецяў для React без стварэння жадных элементаў DOM. Короткая сынтаксіс — это пара пустых тагоў:
return (
<>
<h1>Hello</h1>
<p>Welcome</p>
</>
);
Явны формат React.Fragment рабіць тое ж самае і ўсёрэшчы неабходны, калі трэба перадаць проп:
return (
<React.Fragment>
<h1>Hello</h1>
<p>Welcome</p>
</React.Fragment>
);
Зроблены HTML содержыць толькі h1 і p. Прырост карыстоўнасці мінімальны; справжняя выгода — правільная маркапаўка.
Верненне элементаў-братоў
Компонент, які стварае калькі роўназначных элементаў, можа заставіць распакоўку свайму абяцелю:
function Card() {
return (
<>
<h2>Title</h2>
<p>Description</p>
</>
);
}
Фрагменты з ключамі ў лістах
Калі працуеце з дадзенням, дзе кожны элемент стварае больш ад однаго элемента, React все раве патрэбны стабільны key для кожнага элемента. Короткая сынтаксіс <> не можа прыймаць атрыбуты, таму выкарыстоўваеце React.Fragment з ключам:
items.map(item => (
<React.Fragment key={item.id}>
<h2>{item.title}</h2>
<p>{item.description}</p>
</React.Fragment>
));
Клеткі табелі і рядкі
Тэблы HTML маюць строгія модель кантэнту: элемент tr можа мячыць толькі элементы td або th. Элемент div, які ўкладае іх, там не дапускаецца. Фрагмент дазваляе компоненту дапраўляць калькі клетак у ряд, які належы ўжо його абяцелю:
function Row() {
return (
<>
<td>A</td>
<td>B</td>
</>
);
}
Што пераказвае StrictMode
StrictMode не выводзіць нічога, не дадае жадных элементаў і не мае ніякога адзычлена ў версіях для практычнага выкарыстоўвання. У режыме разработкі ён уваўлекае дадатковыя пераказванні, у тым часе як:
- паведамленні пра методы жыцёвага циклу класаў, якія счыляюцца небезпечнымі, такія як
componentWillMount - паведамленні пра застарэлыя API, такія як рэферэнсы страк і
findDOMNode - двойны выклік тэла компонента, функцый ініцыялізацыі і апдэйта, каб выявіць нечыстае выкананне
- выкананне эфектаў чераз дадатковы цыкл настройкі, чысткі і зноўной настройкі пад час запуску, каб выявіць неадказнае чыстканне
Точны ўказаны список змініўся ў разных версіях React, таму пераканайцеся, што вы бачыце актуальную документацыю для вашай версіі.
Намеравана двойная рэндарызація
Разглянем компонент, які логуе падчас рэндарызаціі:
function App() {
console.log("Rendered!");
return <h1>Hello</h1>;
}
Пад StrictMode пад час розрабоцы консоль паказвае цю прыемку два разы:
Rendered!
Rendered!
Гэта ўзято за прымет. Функцыя рэндарызаціі павінна быць чыстой: пры тых сабе props і стане ў яе вяртаецца той самы выхід, і ў яе не змінюецца нічога паza ёй. Выкліканне яе два разы прыводзіць да нарушэнняў, такіх як змяна спакульнай зменной, і да візуальна некоректных рэзультатаў. Чыстасць мае значэнне, таму што можа пачысцца адночасная рэндарызація, якая може стартаваць, паставляцца, адкладвацца чы працаваць занова, і код, які гадае, што за кожную змяну вядзецца толькі адна рэндарызація, не будзе працаваць за такых умов.
Увімкненне
Абгорніце дрэво, якое вы хочаце пераканацца, зазвычай усю аплікацыю, на корэне:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Эфекты ў режыме StrictMode: массив залежнасцяў — не спосаб рашэння
Ёсць эфект без массива залежнасцяў. Ён выконваецца пасля кожнага атрыбутавання, таму кожная зміна спрычыняе ўтварэнне новага запиту:
useEffect(() => {
console.log("Fetching...");
fetch("/api");
});
Дадзенне пустога массива обмежвае выконанне эфекта толькі часом яго монтавання:
useEffect(() => {
console.log("Fetching...");
fetch("/api");
}, []); // stable dependency
Такая змяна ў правілы, але яна не запобегае двойнаму выконанню у режымі разработки. Зачынення React 18 StrictMode монтавае компонент, выкананыя яго функціі чысткі, і зноў монтавае яго, таму эфект з [] працюе там два разы. Двойнае выкананне — гэта сігнал, а не баг. Праўы спосаб рашэння — функцыя чысткі, якая робіць другае выкананне безнэпакойным, зазвычай абрываючы першы запит за дапамою AbortController або ігнаруючы яго рэзультат за дапамою флага. Такі эфект таксама ў безпецы ад практычных перемонтаванняў у режыме выпуску.
Паралельна
- Мэт: Фрагменты групаваюць элементы;
StrictModeвыяўляе багі. - Выход DOM: ніхто з іх не дадае элемента.
- Уплыв на працэўную сістэму: няма жадных наследкав для або таго.
- Працовае падзея: Фрагменты адрасаваюцца звычайна;
StrictModeдвойна вызывае адрасаванне та эфекты толькі пад час розработы. - Што вы атрымуеце: чыстейшы, правільны маркап у працоўнае супрацоўванне проты прогнозавальнага коду, захіщанага ад побачных эфектаў.
Мінімальная наладка для працы
Компонент нижэй вяртае два братскія элементы через Фрагмент:
export default function App() {
return (
<>
<h1>Hello World</h1>
<p>Rendered using Fragments</p>
</>
);
}
Файл-вхід адрасавае яго ўнутры StrictMode, таму будзь-якая нечыстая логіка, яку вы дадаеце пазней, будзе негайна адкрыта пад час розработы:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Ключовыя выводы
- Вжывайце Фрагмент кожны раз, калі елемент-обгортак існаваў бы толькі для задоволення трэбаванняў JSX, і вжывайце
React.Fragmentзkeyу спісах.
StrictMode працаваць; подвойныя лог-запісы і подвойныя эфекты ўмышлена викорыстоўваюцца як діагностычныя засобы.