Зачем использовать React.memo с функциональными компонентами? - Семидневная регистрация заезда

React.js
Зачем использовать React.memo с функциональными компонентами? - Семидневная регистрация заезда

Эта статья подходит для студентов с основами React, и лучше всего практиковать Hooks Api~

о том, чтоHookЯ серьезно рекомендую вам посмотреть на официальном сайте хорошо.

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

Тогда давайте не будем нести чушь, а сразу перейдем к делу!

Первый взгляд на памятку

Сначала давайте погрузимся в мир React.memo на примере

Глупые функциональные компоненты - памятка не используется

Для функционального компонента, если он не используетсяReact.memoЭто как человек без мозга, упал на простоду

Я не верю, что мы посмотрим на следующую демо

Нажмите, чтобы посетить демонстрацию Давайте проанализируем процесс, который происходит на приведенной выше диаграмме:

  1. При первой загрузке страницы визуализируются компонент App и компонент B, а эффект печати консоли выглядит так, как показано выше.
  2. Нажмите кнопку, чтобы изменить значение внутри компонента приложения. Компонент приложения и компонент Bвсеобновление происходит

Дальше возникает проблема, по нормальной логике должно быть так:

  1. Когда страница визуализируется в первый раз, компоненты App и B обновляются соответственно и печатаются.
  2. Данные в компоненте приложения изменяются, поэтому компонент приложения повторно отображает
  3. Измененные данные не имеют грубой связи с компонентом B, компонент B остается как есть, не обновляется и не отображается.

Но идеал очень пухленький, а реальность очень костлявая. Дело в том, что обновился не только компонент App, но и компонент B. Это не то, что мы хотим, потому что для компонента B: очевидно, я ничего не сделал, но я должен снова носить свою одежду ?

Причина признана недействительной

Тогда причина признана недействительной, Шейн?

На самом деле это просто:

Сам функциональный компонент не распознаетсяpropСпособность значения каждый раз, когда родительский компонент обновляется, эквивалентна передаче нового компонента дочернему компоненту.propстоимость. Так что он эквивалентен компоненту Б. Потому что у него нет мозгов (React.memo), он тупой второй дурак, так что как обычный компонент, разницы нет.propКогда он увидит, что все остальные обновили его способность, он также снова настроит себя, что вызовет проблемы в вышеперечисленном 🌰.

Принеси свой мозг Ханхану - обертка с памяткой

Приведение мозгов к функциональным компонентам Когда мы думаем о функциональном компоненте, мы думаем о следующем:

import React form 'react';

const FuncComponent = ()=>{

	return <h1>火热很火辣</h1>
}

export default React.memo(FunComponent);

Ситуация, подобная описанной выше 🌰, безмозглый компонент рендеринга, не произойдет.

попробуй поставитьвыше демоРаскомментируйте последнюю строку в коде компонента B и попробуйте.

Затем нажмите кнопку еще раз, как указано выше, и увидите вывод консоли:

Ага!只更新了App组件,符合预期!

Так в чем причина этого?

Так что не тут то было, греем дальше 🔥

Страсть накаляется - копай глубже

На данный момент мы все еще не совсем знаем, как memo позволяет избежать недопустимых обновлений, так что давайте посмотрим!

Точки оптимизации производительности в компонентах класса

Я не знаю, обнаружили ли выclassВ компоненте также есть вещь, которая делает это, называемаяPureComponent, его функции иmemoЭто то же самое.

Давайте рассмотрим методы написания, которые мы часто используем в компонентах класса:

import React, {PureComponent} from 'react';

class Demo extends PureComponent {

	// 性能优化点
	shouldComponentUpdate(nextProps, nextState){	
		// 默认始终返回true
		return true;
  	}
	
	render() {
		return <h1>听懂掌声👏</h1>
  	}
	
}

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

Если мы находимся в компоненте класса, не используйте активноPureComponent, вы также можете вручную решить, будет ли компонент обновляться, конкретным методом:

В жизненном циклеshouldComponentUpdate, чтобы пройти токporpsтак же какstateСравните значения и верните логическое значение (true или false), чтобы определить, обновлен ли компонент.

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

Реализация функции памятки

Вот мое предположение,memoпринцип иPureComponentЭто должно быть то же самое.С точки зрения разработчика, поскольку компонент класса имеет такой метод оптимизации, поскольку должен быть реализован Hook, компонент функции также должен нуждаться в аналогичном методе функции, чтобы помочь вам уменьшить нагрузку на оптимизацию кода. Поэтому я считаю, что реализация двух функций должна быть в основном одинаковой. Вот также фрагмент кода для поверхностного сравнения PureComponent в React для вашего дальнейшего понимания.

function shallowEqual (objA: mixed, objB: mixed): boolean {
  //  这里的is是判断两个值是否相等,只不过是对 + 0 和 - 0,以及 NaN 和 NaN 的情况进行了特殊的处理封装,目前react源码中好像有一套新的is判断
  if (is (objA, objB)) {
    return true;
  }
  // 判断是否为对象类型
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

  // 比较两个对象的,属性数量是否相等
  const keysA = Object.keys (objA);
  const keysB = Object.keys (objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // 比较两个对象的的属性是否相等,值是否相等
  for (let i = 0; i < keysA.length; i++) {
    if (
      !hasOwnProperty.call (objB, keysA [i]) ||
      !is (objA [keysA [i]], objB [keysA [i]])
    ) {
      return false;
    }
  }

  return true;
}

Это исходный код для поверхностного сравнения в реакции, а такжеPureComponentа такжеmemoВажная основа для принятия решения об обновлении компонента.

памятка с useMemo, useCallback

Как правило, в области оптимизации проекта,memoОбернутые функциональные компоненты должны быть сопоставленыuseMemoа такжеuseCallbackиспользовать

Что касается useMemo и useCallback, то я не планирую говорить об этом долго и масштабно, потому что в сообществе уже много хороших статей, можете поискать и глянуть. Я просто дам краткое введение здесь.

useCallback

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

Возвращаемое значение является функцией (memoizedCallback), эта функция передается в качестве первого параметра. Разница в том, что эта функция в качестве возвращаемого значения представляет собой мемоизированную версию, которая понимается человеческим языком:Держите ссылку на функцию. Он не будет повторно объявлять функцию при обновлении компонента, тем самым изменяя адрес ссылки в памяти.

Если зависимости во втором массиве аргументов не изменяются, эта функция возвращает значение (memoizedCallback) остается в исходном состоянии

Сценарии применения

Часто используется в родительском компоненте A для передачи функции дочернему компоненту B какpropСтоимость

Родительский компонент А:

import React,{ useCallback } form 'react';

const A = () => {
	
	return (
    	// 如果不使用useCallback包裹的话,每次A的更新,都会重新声明这个handleClick的这个函数,导致B组件无效的更新
     	<B handleClick={ useCallback( () => //doSomething,[x,xx]) };
    );
}

export default A;

Подкомпонент Б:

import React,{ memo } form 'react';

const B = (props) => {
	const { handleClick } = props;
	return <div onClick={ handleClick }>卑微小B在线被Diss</div>;
}
// 这里需要注意,要配合memo使用,否则的话不带脑子的B组件会始终认为传递过来的prop值都是一个全新的
export default memo(B);

useMemo

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

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

useMemoПервый параметр — это функция, возвращаемое значение этой функции будет использоваться как возвращаемое значение useMemo.memoizedValue)

Это используется в качестве возвращаемого значения, если только зависимости во втором массиве аргументов не изменились (memoizedValue) сохраняет исходное значение

UseCallback может делать все, что может useMemo, но рекомендуется выполнять свои собственные обязанности

const fn = useCallback( () => //doSomething , [x,xx])
// 相当于
const fn = useMemo( ()=> () => //doSomething , [x,xx])
// 因为useMemo的返回值是第一个函数的返回值,所以只要让第一个参数的函数返回一个函数就可以达到useCallback的效果

Суммировать

Сегодняшний контент здесь, многие не будут повторяться, и до сих пор не понимают, можем ли мы поднять обсуждение в разделе комментариев или перейти на официальный сайт React, вот небольшой советЕсли вы являетесь пользователем React, я настоятельно рекомендую вам серьезно изучить официальный сайт., Я считаю, что многие разработчики React даже не просматривали самые основные официальные документы веб-сайта. Поверьте мне, если вы внимательно посмотрите на это, вы многое выиграете. Это также ваше самое основное поведение как разработчика React ~

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