Skip to content

Latest commit

 

History

History
406 lines (259 loc) · 16.6 KB

File metadata and controls

406 lines (259 loc) · 16.6 KB

Жизненный цикл

https://ru.reactjs.org/docs/react-component.html

componentDidMount

вызывается сразу после монтирования (то есть, вставки компонента в DOM). В этом методе должны происходить действия, которые требуют наличия DOM-узлов. Это хорошее место для создания сетевых запросов.

componentDidUpdate

вызывается сразу после обновления. Не вызывается при первом рендере.

componentWillUnmount

вызывается непосредственно перед размонтированием и удалением компонента. В этом методе выполняется необходимый сброс: отмена таймеров, сетевых запросов и подписок, созданных в componentDidMount().

Жизненный цикл хуков

Хук эффекта даёт вам возможность выполнять побочные эффекты в функциональном компоненте:

Аналогично componentDidMount и componentDidUpdate:

useEffect(() => {

});

Аналогично componentDidMount

Пустой набор зависимостей [] означает, что эффект будет выполняться только один раз, когда компонент монтируется, а не при каждом повторном рендере.

useEffect(() => {

}, []);

Аналогично componentWillUnmount

useEffect(() => {
    const interval = setInterval(() => {
        setTime(new Date());
    }, 1000);

    return () => clearInterval(interval);
});

Пропуск эффекта

useEffect(() => {
  document.title = `Вы нажали ${count} раз`;
}, [count]); // Перезапускать эффект только если count поменялся

API хуков

useState

Возвращает значение с состоянием и функцию для его обновления.

const [state, setState] = useState(initialState);

const [count, setCount] = useState(initialState);

Во время первоначального рендеринга возвращаемое состояние (state) совпадает со значением, переданным в качестве первого аргумента (initialState).

Функция setState используется для обновления состояния. Она принимает новое значение состояния и ставит в очередь повторный рендер компонента.

setState(newState);

Во время последующих повторных рендеров первое значение, возвращаемое useState, всегда будет самым последним состоянием после применения обновлений.

setCount(prevCount => prevCount - 1)}

setState(prevState => {
  return {...prevState, ...updatedValues};
});

Ленивая инициализация

значения переданные в useState будет применено только один раз при вкл. жизненного цикла в первый рендер

вычисление этого значения может быть достаточной дорогой и тяжелой операцией, а вычисляться оно будет каждый рендер как и все остальные выражения в коде функции компонента

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

useEffect

Чистая функция, возвращает один и тот же результа при неизменных входных параметрах

Сайд эффект - все что изменяет результат функции с течением времени, или это взаимодействия функции с внешним миром(контекстом) по отношению к этой функции

const add = (a,b) => {
  return a + b;
}
let counter = 0
const add = (a,b) => {
  counter++; //side effect
  return a + b;
}

Принимает функцию, которая содержит императивный код, возможно, с эффектами.

useEffect(() => {

}, [])
  1. аргумент - это callback
  2. список зависимостей - своего рода список входящих параметров, в callback

Мутации, подписки, таймеры, логирование и другие побочные эффекты не допускаются внутри основного тела функционального компонента (называемого этапом рендеринга React). Это приведёт к запутанным ошибкам и несоответствиям в пользовательском интерфейсе.

Функция, переданная в useEffect, будет запущена после того, как рендер будет зафиксирован на экране.

По умолчанию эффекты запускаются после каждого завершённого рендеринга, но вы можете решить запускать их только при изменении определённых значений.

Очистка эффекта

функция переданная в useEffect, может вернуть функцию очистки.

Функция очистки запускается до удаления компонента из пользовательского интерфейса, чтобы предотвратить утечки памяти. Кроме того, если компонент рендерится несколько раз (как обычно происходит), предыдущий эффект очищается перед выполнением следующего эффекта.

Порядок срабатывания эффектов

В отличие от componentDidMount и componentDidUpdate, функция, переданная в useEffect, запускается во время отложенного события после разметки и отрисовки. Это делает хук подходящим для многих распространённых побочных эффектов, таких как настройка подписок и обработчиков событий, потому что большинство типов работы не должны блокировать обновление экрана браузером.

Условное срабатывание эффекта

useEffect(() => {
    console.log('this click Heading')
}, [count]);

useLayoutEffect

Сигнатура идентична useEffect, но этот хук запускается синхронно после всех изменений DOM. Используйте его для чтения макета из DOM и синхронного повторного рендеринга. Обновления, запланированные внутри useLayoutEffect, будут полностью применены синхронно перед тем, как браузер получит шанс осуществить отрисовку.

если нужно устранить неконсистентное состояние

useRef

useRef возвращает изменяемый ref-объект, свойство .current которого инициализируется переданным аргументом (initialValue). Возвращённый объект будет сохраняться в течение всего времени жизни компонента.

const refContainer = useRef(initialValue);

Имейте в виду, что useRef не уведомляет вас, когда изменяется его содержимое. Мутирование свойства .current не вызывает повторный рендер.

function getLogger(arg) {
  function logger() {
    console.log(arg)
  }
  return logger
}

let fruit = 'raspberry'
const logFruit = getLogger(fruit)

logFruit() // "raspberry"
fruit = 'peach'
logFruit() // "raspberry" Wait what!? Why is this not "peach"?
function getLatestLogger(argRef) {
  function logger() {
    console.log(argRef.current)
  }
  return logger
}

const fruitRef = {current: 'raspberry'}

const latestLogger = getLatestLogger(fruitRef)

latestLogger() // "raspberry"
fruitRef.current = 'peach'
latestLogger() // "peach" 🎉

useCallback

Возвращает мемоизированный колбэк.

Хук useCallback вернёт мемоизированную версию колбэка, который изменяется только, если изменяются значения одной из зависимостей.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useMemo

Возвращает мемоизированное значение.

Передайте «создающую» функцию и массив зависимостей. useMemo будет повторно вычислять мемоизированное значение только тогда, когда значение какой-либо из зависимостей изменилось. Эта оптимизация помогает избежать дорогостоящих вычислений при каждом рендере.

Помните, что функция, переданная useMemo, запускается во время рендеринга. Не делайте там ничего, что вы обычно не делаете во время рендеринга. Например, побочные эффекты принадлежат useEffect, а не useMemo.

Вы можете использовать useMemo как оптимизацию производительности, а не как семантическую гарантию.

Все объекты и массивы которые вы используите внутри компонента и передаете куда то пропсами, необходимо мемоизировать

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Example

const searchQuery = 'Mag'
const items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: 12 },
  { name: 'Magnetic', value: 5 },
  { name: 'Zeros', value: 37 }
];

const sort = () => {
  return [...items].sort((a,b) => a.value - b.value);
}

const search = () => {
  return sort().filter(item => item.name.includes(searchQuery))
}
const searchQuery = 'Mag'

const items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: 12 },
  { name: 'Magnetic', value: 5 },
  { name: 'Zeros', value: 37 }
];

const sort = useMemo(() => {
  return [...items].sort((a,b) => a.value - b.value);
}, [items])


const search = useMemo(() => {
  return sort().filter(item => item.name.includes(searchQuery))
}, [searchQuery, sort])

React.memo - аналог pureComponents

https://ru.reactjs.org/docs/react-api.html#reactmemo

React.memo — это компонент высшего порядка.

Если ваш компонент всегда рендерит одно и то же при неменяющихся пропсах, вы можете обернуть его в вызов React.memo для повышения производительности в некоторых случаях, мемоизируя тем самым результат. Это значит, что React будет использовать результат последнего рендера, избегая повторного рендеринга.

React.memo затрагивает только изменения пропсов. Если функциональный компонент обёрнут в React.memo и использует useState, useReducer или useContext, он будет повторно рендериться при изменении состояния или контекста.

useContext

https://ru.reactjs.org/docs/context.html

Контекст позволяет передавать значение глубоко в дерево компонентов без явной передачи пропсов на каждом уровне.

Обычно контекст используется, если необходимо обеспечить доступ данных во многих компонентах на разных уровнях вложенности. По возможности не используйте его, так как это усложняет повторное использование компонентов.

Prop-Drilling

https://ru.reactjs.org/docs/context.html

https://beta.reactjs.org/learn/passing-data-deeply-with-context

https://habr.com/ru/company/ncloudtech/blog/685400/

практика передачи одного свойства на несколько уровней от родительского компонента к дочернему.

alt

Решение:

  • context
  • композиция
  • рендер-пропсы
  • state management

Compound component

https://habr.com/ru/company/alfa/blog/647013/

https://www.smashingmagazine.com/2021/08/compound-components-react/

https://beta.reactjs.org/learn/sharing-state-between-components

Compound components это подход, в котором вы объединяете несколько компонентов одной общей сущностью и общим состоянием. Отдельно от этой сущности вы их использовать не можете, тк они являются единым целым. Это как в BEM нельзя использовать E - элемент, отдельно от B - блока.

<select name="meals">
  <option value="pizza">Pizza</option>
  <option value="pasta">Pasta</option>
  <option value="borsch">Borsch</option>
  <option value="fries">Fries</option>
</select>

<Select>
  <Option value="pizza" />
  <Divider />
  <Option value="pasta" />
  <Option value="borsch" />
  <Option value="fries" />
</Select>

Render Props

https://ru.reactjs.org/docs/render-props.html

https://ant.design/components/table/

Термин «рендер-проп» относится к возможности компонентов React разделять код между собой с помощью пропа, значение которого является функцией.

Динамичный компоненет

https://codesandbox.io/s/01-loading-components-dynamically-without-switch-statement-c9bwv?file=/src/App.js

Композиция

https://ru.reactjs.org/docs/composition-vs-inheritance.html

Higher-Order Component и Container Components

Компонент высшего порядка — это функция, которая принимает компонент и возвращает новый компонент.

HOC — это инструмент для параметризированного создания контейнеров.

const withHigherOrderComponent = (Component) => (props) =>
  <Component {...props} />;

https://www.patterns.dev/posts/hoc-pattern/

https://www.patterns.dev/posts/presentational-container-pattern/

https://ant.design/components/checkbox/

CSS

https://github.com/css-modules/css-modules

https://www.npmjs.com/package/classnames

install

https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint

https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi

read

https://www.patterns.dev

https://www.developerway.com/posts/react-re-renders-guide

https://www.youtube.com/watch?v=GNrdg3PzpJQ