Поделитесь некоторыми заметками по программированию, которые я сделал в прошлом, которые помогли мне понять концепции, и это вопросы, которые вам могут задать во время интервью.
Реагировать
Что такое Реакт?
- Библиотека пользовательского интерфейса (для создания пользовательских интерфейсов)
- Компонентная архитектура (разные функции управляют разными частями пользовательского интерфейса)
- Поток данных в React (односторонний поток данных сверху вниз, компонент к дочерним элементам)
- Состояние компонента (управление своим состоянием и передача потомкам)
- Рендеринг + обновление пользовательских интерфейсов, обработка пользовательского ввода
Что такое Компонент?
- React — это компонентный язык
- React позволяет создавать сложные пользовательские интерфейсы из небольших и независимых фрагментов кода, называемых «компонентами».
- Компоненты подобны функциям, которые возвращают HTML-элементы, сообщающие, что должно отображаться на экране (через функцию render()).
- Компоненты — это основные строительные блоки пользовательского интерфейса, которые можно использовать повторно, вы можете использовать компонент на разных страницах, а компоненты независимы.
В React все является компонентом.
- Библиотека React as UI (пользовательский интерфейс) зависит от компонентов как от независимого и многократно используемого фрагмента кода, который вы можете использовать в любом месте своего приложения.
Что такое JSX?
- JSX расшифровывается как JavaScript XML, он позволяет нам писать HTML в React и обладает всеми возможностями JavaScript.
- JSX упрощает написание и добавление HTML в React и легко создает пользовательские интерфейсы для ваших веб-приложений.
- Старые браузеры несовместимы с JSX, и React использует babel для преобразования кода в старый синтаксис JS для работы с браузером.
Что такое виртуальный DOM?
- DOM — это дерево узлов, которое создается браузером после разбора HTML в процессе критического пути рендеринга. React берет копию этого DOM и сохраняет ее в памяти => виртуальный DOM.
- Когда вы вносите какие-либо изменения или инициируете какое-либо действие, которое в конечном итоге обновит представление, React создает новую копию виртуального DOM и применяет обновления к новой копии.
- React проведет сравнение с использованием алгоритма сравнения между деревьями, найдет различия и объединит обновления в реальный DOM, проще говоря, заменит старые узлы новыми узлами.
Как обновляется виртуальный DOM?
- Когда вы что-то меняете, виртуальный DOM сравнивается с реальным DOM перед любыми обновлениями на странице.
- React определит, какие объекты изменились.
- Только измененные объекты обновляются в реальном DOM.
- Изменения в реальном DOM вызывают изменение экрана.
- Когда вы пытаетесь обновить DOM в React, обновляется весь виртуальный DOM.
Преимущество виртуального DOM
- Он не перерисовывает весь DOM, а только измененные узлы.
- Это не приводит к падению производительности
- Обновление виртуального DOM сравнительно быстрее, чем обновление фактического DOM (манипулирование реальным DOM очень дорого).
Плюсы реакции
- Легко учиться - › Сильная поддержка сообщества
- Компонентная структура -> Возможность повторного использования
- VirtualDOM -> избегайте ненужного повторного рендеринга, манипулирование реальным DOM очень дорого
- Алгоритмы различий (выводит набор различий между двумя входными данными) -> согласование («виртуальное» представление пользовательского интерфейса хранится в памяти и синхронизируется с «реальным» DOM с помощью такой библиотеки, как ReactDOM)
- JSX (HTML + JS) -> писать HTML внутри JavaScript, хорошо для разработчиков — теперь можно избежать эффективного переключения контекста
- Сосредоточьтесь на представлении -> Пользовательские интерфейсы
- хуки и жизненный цикл компонента -> позволяют нам контролировать, как наш компонент должен вести себя в течение своего жизненного цикла, используя различные хуки.
Какие проблемы решает React?
- улучшенная обработка динамических данных для более быстрого отклика
- и мгновенная реакция на изменение данных
- визуализирует правильные компоненты для удобного взаимодействия с пользователем.
оказывать()
- он отображает HTML-элементы, содержащиеся в компоненте, в DOM.
состояние
- state — это объект, который содержит данные, находящиеся внутри текущего компонента в виде локальных переменных или переменных экземпляра.
- состояние — это данные, которые вы можете изменить внутри компонента, чтобы затем принудительно переоценить этот компонент.
- это объект, внутренне захваченный классом (в конструкторе this.state)
- объект, управляющий поведением компонента, может изменяться в течение времени жизни компонента.
государственная цель
- Он используется для рендеринга данных в DOM.
- Он используется для передачи в качестве реквизита дочернему компоненту.
- Используется для интеграции с методом или функцией
реквизит
- реквизиты — это данные, которые вы передаете от родительского компонента к дочернему компоненту.
- реквизит вниз, родитель разговаривает с ребенком
- Может ли ребенок возражать родителю, используя реквизит? НЕТ -› использование обратного вызова
супер (реквизит)
- конструктор(реквизит) -> инициализировать состояние объекта в классе, вызываемом до его монтирования
- super(props) -> вызвать конструктор родительского класса() компонента React в качестве ссылки
Подъем состояния вверх
- Чтобы подкомпоненты общались друг с другом через родителей
- состояние совместного использования достигается путем перемещения локального состояния до ближайшего общего предка компонентов, которые в нем нуждаются.
- поднимая состояние вверх, мы делаем состояние родительского компонента единым источником правды и передаем данные вниз подкомпонентам
Поднятие состояния против композиции против наследования
- Подъем состояния: позволяет дочерним компонентам лучше общаться друг с другом.
- Состав: {props.children} — передается как дочерние свойства, содержит любые дочерние элементы, определенные в компоненте.
- Наследование: не лучшая модель для использования в React
Какие побочные эффекты?
- Побочные эффекты — это в основном все, что влияет на что-то, выходящее за рамки текущей выполняемой функции.
- Пример: запросы API к нашему серверному сервису.
Как вы синхронизируете эффекты в компоненте React с изменениями в определенных состояниях или свойствах?
- во-первых, мы сохраняем состояния/реквизиты в родительском компоненте, то есть в том компоненте, где мы запускаем событие onClick; затем, чтобы передать состояние другому компоненту, мы просто передаем его как свойство.
- useEffect вызывается после того, как React уже фиксирует обновления, т. е. обновления будут отражены в DOM; затем вы обновите состояние, которое снова обновит DOM. Второй способ вызывает повторный рендеринг, но коммит в DOM только один.
useEffect(() => { // Called on first render and every props.foo update }, [props.foo])
Функциональный компонент
- Чистая функция — это функция, которая не имеет побочных эффектов, не изменяет данные за пределами области действия функции и не зависит ни от какого внешнего состояния, а только от переданных ей входных данных.
- будет отображать один и тот же вывод для одного и того же ввода (состояния и реквизиты)
Компонент с состоянием против компонента без состояния
- компоненты с отслеживанием состояния отслеживают изменение данных
- компоненты без состояния всегда отображают одно и то же, распечатывают то, что им дается через реквизиты
Элемент против компонентов в React
- React Element похож на HTML-элемент, неизменный объект, описывающий DOM-узел, к нему нельзя применять какие-либо методы.
- Компонент React — это функция или класс, который принимает ввод и возвращает элемент React.
Списки и ключи
- ключ помогает React определить, какие элементы были изменены (добавлены/удалены/переупорядочены) для отображения
- дать уникальный идентификатор каждому элементу внутри массива, требуется ключ.
- ключ — это уникальный элемент для перебора подкомпонентов, всегда добавляйте ключ на уровень выше!
{ this.state.numArr.map((num, index) => ( <Child key={index} num={num} /> ))}
Ключ, не использующий индексы
- не рекомендуется использовать индексы для ключей, особенно порядок элементов может измениться — плохой дизайн.
- Если ключ является индексом, изменение порядка элемента изменяет его.
- Состояние компонента может быть перепутано и может использовать старый ключ для другого экземпляра компонента.
- Кроме того, итерация по списку, когда он большой, приводит к снижению производительности.
[a:0, b:1, c:2]
->[d:0, a:1, b:2, c:3]
- плохо[d:unique key, a:unique key, b:unique key]
- хорошо
Атрибуты
defaultChecked
- устанавливает, проверяется ли компонент при первом монтировании в<input>
dangerouslySetInnerHTML
– Способ замены React для использования innerHTML в DOM браузера является рискованным, поскольку легко непреднамеренно подвергнуть ваших пользователей атаке с использованием межсайтового скриптинга (XSS) –<div dangerouslySetInnerHTML={__html: description} />
className
,onChange
,htmlFor
,selected
,value
,style
,tabIndex
,readOnly
создатьПортал()
- визуализировать дочерние элементы в узел DOM, ведет себя как обычный дочерний элемент React, но также включает всплытие событий, поскольку в дереве DOM
- создание модальных окон, диалогов, всплывающих подсказок и всплывающих подсказок. с порталами вы можете отображать параллельное дерево реакций на другой узел DOM, когда это необходимо.
ReactDOM.createPortal(child {any renderable React child}, container {a DOM element})
Синтетическое событие
- вся оболочка над системой событий DOM может иметь большой вес в кодовой базе React, не используя addEventListener браузера для внутренней обработки событий
- потому что мы запускаем React в разных средах, поэтому нам нужна согласованность в нескольких браузерах, например, в оболочке.
- согласованность -> обертка (basicEvent) => кросс-браузерная оболочка вокруг собственного события браузера
Реагировать. Фрагмент
- выглядит чище, избегайте слишком большого количества
<div>
<React.Fragment>...</React.Fragment>
Соглашение об именовании
[Domain]|[Page/Context]|ComponentName|[Type]
- Домен: какому продукту принадлежит этот компонент?
- Страница или контекст: что является родительским компонентом? к какой части/странице продукта относится этот компонент?
- Компонент: что делает этот компонент? например боковая панель, короткий список, чат
- Типы компонентов: вид, кнопка, подключение, ввод, загрузка
Рендеринг
Повторно отображает ситуации
- Родительский компонент выполняет повторный рендеринг, в результате чего все дочерние элементы родителя пытаются выполнить повторный рендеринг, даже если реквизиты родителя не изменились.
- Компонент вызывает this.setState(), что вызывает обновление состояния и повторную визуализацию.
- Компонент вызывает this.forceUpdate(), что вызывает повторный рендеринг.
- Замена компонента? Рендеринг. Родитель изменился? Рендеринг. Раздел реквизита, который на самом деле не влияет на вид, изменился? Рендеринг.
Что делает setState?
- setState вызовет повторный рендеринг и правильно обновит/изменит локальное состояние.
- когда используется предыдущее значение, мы всегда должны использовать функцию обратного вызова, чтобы правильно обрабатывать его на основе текущего значения.
this.setState((prevState) => { //passing in a callback function instead of setState directly return { number: prevState.number + 1 }; })
Зачем нам обратный звонок?
- useState и setState являются асинхронными.
- Они не обновляют состояние немедленно, но имеют очереди, которые используются для обновления объекта состояния.
- Используйте функцию обратного вызова для setState, чтобы он правильно отображал предыдущее значение, а не просто присваивал новый объект.
- React объединит несколько setState в одно обновление для выполнения изменения состояния из-за производительности рендеринга компонентов React.
setState() за кулисами
- setState являются асинхронными и группируются для повышения производительности —> реагировать на волокно —> затем рендерить
- волокно: согласование, алгоритмы сравнения — выводит набор различий между двумя входными данными —> нет нового ключа, нет изменений в виртуальном DOM, улучшается производительность сети.
- Пакетная обработка: React группирует несколько обновлений состояния в один повторный рендеринг для повышения производительности.
- используя setState для изменения переменной внутри любой функции, вместо того, чтобы выполнять рендеринг в каждом setState, React собирает все setState, а затем выполняет их вместе.
- независимо от того, сколько вызовов setState вы делаете внутри обработчика событий React или синхронного метода жизненного цикла, они будут объединены в одно обновление.
Пользовательский интерфейс материала
- Простая и настраиваемая библиотека компонентов, которая позволяет нам импортировать и использовать различные компоненты для создания пользовательского интерфейса в нашем приложении React.
- Экономит значительное количество времени, так как разработчикам не нужно писать все с нуля.
CSS-модуль
import styles from "./Button.module.css";
- импортировать модули CSS, также изменить имя файла CSS<button type={props.type} className={styles.button} onClick={props.onClick}>
Стилизованные компоненты
- пакет, помогающий создавать компоненты, к которым прикреплены определенные стили (CSS-in-JS)
import styled from "styled-components"; export const Button = styled.button`color: white;` //using tagged template literal
Контролируемый компонент против неконтролируемого компонента
Контролируемый компонент
- Данные обрабатываются компонентом React ‹-› значение ввода всегда управляется состоянием React
- Изменение состояния имеет связанную функцию-обработчик, управляющую собственным состоянием и передающую новые значения в качестве реквизита контролируемому компоненту.
- принимает свое текущее значение через свойства, а родительский компонент «управляет» им, обрабатывая обратные вызовы, такие как onChange.
- рекомендуем использовать контролируемые компоненты для реализации форм
- компонент, который отображает элементы формы и управляет ими, сохраняя данные формы в состоянии компонента.
<ControlledComp value={this.props.fromParent} onChange={this.props.handleChange} />
const { useState } from 'react'; function Controlled () { const [email, setEmail] = useState(); const handleInput = (e) => setEmail(e.target.value); return <input type="text" value={email} onChange={handleInput} />; }
Неконтролируемый компонент
- Данные обрабатываются самой DOM.
- немного больше похож на традиционный HTML, сохраняет единственный источник правды в DOM,
- вы запрашиваете DOM, используя ref, чтобы найти его текущее значение, когда вам это нужно.
- Рефы предоставляют способ доступа к узлам DOM или элементам React, созданным в методе рендеринга.
import React, { Component } from 'react'; export class App2 extends Component { constructor(props){ super(props); this.handleChange = this.handleChange.bind(this); this.input = React.createRef(); //access the input DOM node and extract its value } handleChange = (newText) => { console.log(newText); } render() { return ( <div className="App2"> <input type="text" ref={this.input} onChange={(event) => this.handleChange(event.target.value)} /> </div> ); } }
HOC
HOC -> компонент высокого порядка
- HOC — это шаблон, в котором функция принимает компонент в качестве аргумента и возвращает новый компонент в соответствии с определенным логическим шаблоном повторного использования компонента.
- возьмите исходный компонент и добавьте некоторые украшения и модификации, а также реквизит, чтобы сделать его новым компонентом, добавьте больше содержимого
- пример: подключение в React-Redux
connect(a, b)(OriginalComp)
Почему ХОК?
- используйте его для повторного использования, чтобы разделить общие функции между компонентами
- тот же шаблон, но применяется только к тому, когда он нам нужен, и просто удаляем его, когда он нам не нужен
Пример HOC
import React from "react"; const UpdatedComponent = (OriginalComponent) => { class NewComponent extends React.Component{ render() { return <OriginalComponent name="inject props"/> } } return NewComponent } export default UpdatedComponent; import ContentContainer from "../HOC/ContentContainer"; const HOCCounter = UpdatedComponent(Counter); export default HOCCounter;
Маршрутизатор
Что такое React Router?
- Отличный способ создания одностраничных приложений, поскольку вы предотвращаете обновление страницы при каждом нажатии ссылки.
- При рендеринге на стороне клиента страница не обновляется при переходе по различным ссылкам.
- Несколько страниц в одностраничном приложении, изменения URL, изменения видимого содержимого.
Традиционная многостраничная маршрутизация
- HTML запрашивается и загружается; Изменение страницы = новый запрос + ответ (рендеринг на стороне сервера).
Одностраничное приложение
- Только один начальный HTML-запрос и ответ, изменения страницы (URL) затем обрабатываются кодом на стороне клиента (React) -> изменяет видимое содержимое без загрузки нового HTML-файла (рендеринг на стороне клиента).
- Цель состоит в том, чтобы мы могли обрабатывать разные пути на нашей странице и загружать (рендерить) разные компоненты для разных путей.
Ссылка против маршрута
- Компонент Link отвечает за переход из состояния в состояние (страница на страницу)
- Компонент маршрута отвечает за то, чтобы действовать как переключатель для отображения определенных компонентов в зависимости от состояния маршрута.
использоватьпараметры()
- Возвращает объект параметров для отображаемого маршрута.
// route: /user/:userName const params = useParams(); return <h1>{params.userName}</h1>
использоватьRouteMatch();
- пытается сопоставить текущий URL
let match = useRouteMatch(); <Link to={`${match.url}/components`}>Components</Link> <Route path={`${match.path}/:topicId`}>
Реализация маршрутизатора React
import React from "react"; import { BrowserRouter as Router, Switch, Route, Link, } from "react-router-dom"; export default function App() { return ( <Router> <div> <ul> <li> <Link to="/">Home</Link> </li> </ul> <Switch> <Route path="/about"> <About /> </Route> <Route path="/"> <Home /> </Route> </Switch> </div> </Router> ); }
Жизненный цикл
Компонент класса против функционального компонента
- мы используем компонент класса, когда компонент имеет собственное локальное состояние и жизненный цикл до React 16.8.
- теперь мы можем использовать хуки реагирования для выполнения локального состояния и жизненного цикла в функциональном компоненте
Эффекты жизненного цикла
- Функции запускают код, когда компонент создается, обновляется или удаляется со страницы.
Жизненный цикл (3 фазы) — монтирование, обновление, размонтирование
- Монтаж (constructor() и render()): конструктор инициализации -> присваивает начальное this.state, а компоненты рендеринга —> у нас есть поверх начального рендера в DOM
- componentDidmount (начальный рендер) -> только после начального рендера мы вызываем componentDidMount
- Обновление: когда компонент обновляется в результате изменения состояния или изменения свойств.
- componentDidUpdate (обновление) -> когда мы обновляем, нам нужно изменить какое-то состояние, чтобы вызвать повторный рендеринг
- Размонтирование: когда компонент удаляется из DOM.
- componentWillUnmount -> правильная очистка для предотвращения утечки памяти (удалить eventListener, удалить setTimeout)
использоватьЭффект()
- принимает два параметра, 1-й — функция обратного вызова, 2-й — массив зависимостей
- возвращаемая функция будет вызываться после удаления компонента
- мы можем сделать очистку в возвращаемой функции
function XXX () { const [name, setName] = useState(""); useEffect(() => { console.log("This is component did mount"); return () => { console.log("This is component did unmount"); console.log("returned function will be called on componentWillUnmount, for clean up, uunmount first then updates"); } }, []) //no dependencies here, so only the first render useEffect(() => { console.log("This is component did update"); }, [name]) //will be called whenever the dependency updates return <p>This is render.</p> }
React.PureComponent против памятки
- Та же функциональность, оба предназначены для повышения производительности, React.memo — это компонент более высокого порядка — оболочка.
- С PureComponent или memo он уже содержит логику shouldComponentUpdate — сравнивает пропсы
- Чтобы сравнить текущие реквизиты и предыдущие реквизиты, чтобы убедиться, что они отсекают ненужные рендеры.
Неглубокое сравнение — React.memo()
- React.memo() выполняет поверхностное сравнение реквизита и объектов реквизита.
- В JavaScript поверхностное сравнение объектов всегда будет возвращать false, даже если они имеют одинаковые значения.
- Если вам нужен больший контроль и ответственность за это сравнение, React.memo принимает второй аргумент — функцию сравнения.
Граница ошибки
- только компонент класса, определите один или оба метода жизненного цикла getDerivedStateFromError (рендеринг резервного пользовательского интерфейса после возникновения ошибки) и componentDidCatch (регистрация информации об ошибке)
- ловить ошибки JS в дочернем дереве компонентов, регистрировать эти ошибки и отображать резервный пользовательский интерфейс
- отсутствие границ ошибок в обработчике событий, асинхронные коды, рендеринг на стороне сервера, ошибки, выбрасываемые сами по себе, чем дочерние элементы
Граница ошибки vs Try…Catch…
- Try…catch имеет дело с императивным кодом: как вы что-то делаете, вы можете отлавливать ошибки в своем коде.
- Границы ошибок связаны с декларативным кодом: то, что вы делаете, например, в случае ошибки, вы можете вызвать резервный пользовательский интерфейс.
Крючки
Что такое хуки?
- Хуки — это функции, которые позволяют вам «подключаться» к функциям состояния и жизненного цикла React из функциональных компонентов.
- Хуки не работают внутри компонентов класса. Вы также можете создавать свои собственные хуки для повторного использования поведения с отслеживанием состояния между различными компонентами.
использовать состояние()
const [state, setState] = useState(initialState)
- функция значения и установки
const computationInit = () => return 0; function App() { const [count, setCount] = useState(() => computationInit()); //callback function, only called at the initial time const [name, setName] = useState(""); //another local state, initial state in () return ( <> <button onClick={() => setCount(count + 1)}>+</button> <div>Count Number {count}</div> <button onClick={() => setName("Hello")}>show name</button> <div>{name}</div> </> ); } export default App; function App() { const [{ count1, count2 }, setCount] = useState({ count1: 1, count2: 2 }); return ( <> <button onClick={() => setCount((prevState) => { //without ...prevState, it overwrites the object return { ...prevState, //...prevState first - give all the key I have then make modification to the count1 count1: prevState.count1 + 1 //we only modify count1 without changing/overriding count2 }; }) } > + </button> <div>Count 1 - {count1}</div> <div>Count 2 - {count2}</div> </> ); }
использоватьЭффект()
- создать побочный эффект, когда что-то происходит или меняются зависимости: «Если какая-то переменная изменится, сделайте это».
- useEffect запускается после анализа DOM из-за асинхронного характера JS.
useEffect(...,[])
: componentDidMount() — вызывается после монтирования компонента (оценка и визуализация)useEffect(..., [someValue])
: componentDidUpdate() — вызывается после обновления компонента (был оценен и отрендерен)useEffect(() => {return () => {...}}, [])
: componentWillUnmount() - вызывается непосредственно перед размонтированием компонента (удалением из DOM)
function XXX () { const [name, setName] = useState(""); useEffect(() => { console.log("This is component did mount"); return () => { console.log("This is component did unmount")' } }, []) //empty array -> ComponentDidMount (no dependency, we call it after every render) //with dependencies in the array, will be called when the value changes useEffect(() => { console.log("This is component did update"); }) return <p>This is render.</p> }
useEffect() + Аксиос
- В useEffect сделайте запрос, есть ли сетевая ошибка или нет, и установите тайм-аут, чтобы время выборки не было бесконечным.
React.useEffect(() => { (async () => { try { const result = await Axios.get( "http://media.xiph.org/mango/tears_of_steel_1080p.webm", { timeout: 5000} ); // Do something here } catch (e) { console.log("The link is not avaible", e.message); // Do something here } })(); }, []);
использоватьСсылка()
- запросите DOM, используя ref, чтобы найти его текущее значение, когда вам это нужно (используйте ref для ссылки на элементы внутри вашего HTML)
- ref сохраняет значение постоянным, но не вызывает повторного обновления вашего компонента при его изменении, тогда как setState запускает повторный рендеринг
- когда вам нужно изменить какое-либо значение, по-прежнему используйте setState()
const [name, setName] = useState('') const inputRef = useRef() const prevName = useRef('') function focus(){ inputRef.current.focus() //inputRef.current refers to <input value> } if (name === inputRef.current.value) { } useEffect(() => { prevName.current = name }, [name]) return ( <> <input ref={inputRef} value={name} onChange={e => setName(e.target.value)}/> <div>My name is {name}, used to be {prevName.current}. </div> <button onClick={focus}>Focus</button> </> ) }
использоватьконтекст()
- указать определенные фрагменты данных, которые будут доступны всем компонентам, вложенным в контекст, без необходимости передавать эти данные через каждый компонент
export const ThemeContext = React.createContext()
инициировать контекст, значения по умолчанию, фактически не используемые, но для автозаполненияconst [darkTheme, setDarkTheme] = useState(true)
<ThemeContext.Provider value={darkTheme}>{everything has the access to the value props}</ThemeContext.Provider>
- класс:
<ThemeContext.Consumer>{value is available to the component}</ThemeContext.Consumer>
- function:
const darkTheme = useContext(ThemeContext)
- тогда darkTheme доступна для использования в компоненте
использоватьредусер()
- обработка сложного управления взаимодействием состояний, альтернатива useState
- редуктор принимает 2 параметра, функцию и начальное значение и возвращает одно значение
function reducer(state, action) { return {} }
- обычно переключаются случаи с action.type, который отправляется редюсеру для измененийconst [state, dispatch] = useReducer(reducer, initialState)
- InitialState всегда имеет объекты типа[]
{count:0}
function increment() { dispatch({ type: "increment" }) }
- отправить тип действия редюсеру
const ingredientReducer = (currentIngredients, action) => { switch (action.type) { case 'SET': return action.ingredients; case 'ADD': return [...currentIngredients, action.ingredient]; case 'DELETE': return currentIngredients.filter(ing => ing.id !== action.id); default: throw new Error('Should not get there!'); } }; const httpReducer = (curHttpState, action) => { switch (action.type) { case 'SEND': return { loading: true, error: null }; case 'RESPONSE': return { ...curHttpState, loading: false }; case 'ERROR': return { loading: false, error: action.errorMessage }; case 'CLEAR': return { ...curHttpState, error: null }; default: throw new Error('Should not be reached!'); } }; const [userIngredients, dispatch] = useReducer(ingredientReducer, []); const [httpState, dispatchHttp] = useReducer(httpReducer, { loading: false, error: null }); const filteredIngredientsHandler = useCallback(filteredIngredients => { dispatch({ type: 'SET', ingredients: filteredIngredients }); dispatchHttp({ type: 'SEND' }); dispatchHttp({ type: 'RESPONSE' }); dispatch({ type: 'DELETE', id: ingredientId }); }, []); const clearError = () => { dispatchHttp({ type: 'CLEAR' }); };
Производительность реакции — useMemo() и useCallback()
- как для предотвращения ненужных повторных рендеров, так и для повышения эффективности вашего кода.
- кэшировать функцию в функциональном компоненте с массивом зависимостей
.useCallback()
- запомнить актуальную функцию
- избегая ненужных рендеров от дочернего элемента, меняйте ссылку только при изменении зависимостей
- используйте его, когда функция зависит от побочного эффекта
- сохранить функцию, которая не изменяется, чтобы не генерировалась новая функция
- точно так же, как useMemo, не будет повторно запускать код внутри него, если не будет изменен определенный параметр
- возьмите функцию, которая возвращается useCallback, сохраняет ее в переменной, а позже вы можете использовать ее как
getItems(1)
- Возвращает запомненный обратный вызов. useCallback запомнит вашу фактическую функцию.
const getItems = useCallback((incrementor) => { //return us the entire function return [number + incrementor, number + incrementor + 1, number + incrementor + 2] }, [number])
.useMemo()
- запомнить значение из функции
- запускаться при каждом рендеринге, но с кэшированными значениями, будут использовать новые значения только при изменении определенных зависимостей.
- useMemo принимает два аргумента: функцию и список зависимостей, каждый раз, когда useMemo сначала проверяет, изменились ли какие-либо зависимости
- Если нет, он вернет кэшированное возвращаемое значение, не вызывая функцию. (запоминать, кэшировать, не нужно пересчитывать)
- Если они изменились, useMemo снова вызовет предоставленную функцию и повторит процесс.
- Возвращает запомненное значение. useMemo запомнит возвращаемое значение из вашей функции.
const doubleNumber = useMemo(() => { //only return the value of the function return slowerFunction(number) }, [number])
Контекст
Что такое React-контекст?
- Контекст предоставляет способ передачи данных через дерево компонентов без необходимости вручную передавать реквизиты на каждом уровне.
- С помощью контекста мы можем напрямую получить значение для вложенных дочерних элементов.
- Без Redux и React Context нам нужно поднимать состояние вверх.
Как использовать контекст
export const Context = React.createContext()
- инициировать контекст и значения по умолчанию, не используемые на самом деле, а для автозаполнения- класс: Использование
< Context.Provider value={} >
и< Context.Consumer >
для переноса кода возврата - функция: использование
< Context.Provider value={} >
и использование хука useContext, затемconst value = useContext(Context)
Реагировать против Редукса
- У вас может быть несколько контекстов, но только одно хранилище в Redux.
- Если вы используете React Context, это может привести к загрязнению данных, поскольку потребитель ищет ближайшего предка поставщика.
- defaultValue ‹=› всплывающее — всегда поднимайтесь, чтобы посмотреть на ближайшую родословную
- В контексте GrandChild.js — ищите дочернее значение, но не родительское.
- мы можем ошибаться или не сможем получить желаемое значение, так как значение передается в GrandChild, ближайшим предком является Child
Когда будет здорово использовать Context?
- Redux — более масштабное приложение
- Контекст — Приложение меньшего масштаба
Недостатки по сравнению с Redux
- сложная настройка/управление может привести к глубоко вложенному коду JSX и/или огромному компоненту поставщика контекста
- производительность, контекст реакции не оптимизирован для высокочастотных изменений состояния