Понимание хуков React

JavaScript Тенсент машинное обучение React.js

Приветствую всех вОблако Tencent + сообщество, получить больше крупной технической практики Tencent по галантерее ~

Эта статья написанаЧжиханОпубликован вКолонка «Облако + сообщество»

TL;DR

Одним предложением React Hooks находится в функциональном компоненте реакции, вы также можете использовать состояние и жизненный цикл компонентов компонентов класса, не переключаясь между миксинами, функциональными компонентами, компонентами HOC и реквизитами рендеринга, создавая функциональные компоненты. практичнее, и нам удобнее реализовать разделение кода бизнес-логики и повторное использование компонентов в бизнесе.

В этой статье будут представлены хуки из следующих аспектов

Какие проблемы решают хуки Знакомство с API хуков и как использовать хуки Как реализованы хуки?

💡Какие проблемы решают хуки?

React решает проблему, как отделить код бизнес-логики и реализовать повторное использование связанной бизнес-логики внутри компонента.

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

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

Здесь на помощь приходят крючки. Хуки позволяют нам организовать логику внутри компонента в многоразовый изолированный модуль.

Чтобы проиллюстрировать проблему с двумя диаграммами @Sunil Pai:

img
image.png

img
image.png

То, что мы испытываем от React Hooks, — это реализация философии React внутри компонентов.В прошлом мы только напрямую отражали философию React в компонентах и ​​компонентах, то есть четкий и понятный поток данных и композиция. Логику в компоненте можно переиспользовать, а привнесенные HOC слои вложенности не появятся, и он не появится.Недостатки Миксина.

💡Введение в API хуков и как использовать хуки

@dan_abramov познакомил нас с тремя ключевыми API хуков на конференции, а именноState Hooks,Effect Hooks,Custom Hooks(自定义hooks)

📌 Хуки состояния (useState)

Метод useState переносит в наш функциональный компонент локальное состояние, принимает значение начального состояния и возвращает пару переменных. Пусть функциональные компоненты имеют свои собственные компоненты.

Прежде всего, что, если нам нужно использовать компонент классов для реализации компонента «Кнопка нажатия +1»?

import React from 'react';

class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: 0};
        this.clickBtn = this.clickBtn.bind(this);
    }
    clickBtn = () => {
        this.setState({
            count: this.state.count + 1;
        });
    }
    return (
        <div>
            <p>You clicked {this.state.count} times</p>
            <button onClick={this.clickBtn}>
                Click me
            </button>
        </div>
    );
}

Итак, на что похоже использование useState? Это видно очень четко.

// 一个简单的点击计数
import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

📌Крюки эффектов (useEffect)

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

import { useState } from 'react';

function windowWidth() {
    const [width, setWithd] = useState(window.innerWidth);
    useEffect(() => {
        const handleResize = ()=>{
            setWidth(window.innerWidth);
        }
        window.addEventListener('resize', handleResize);
    });
    return (
        <p> window width is {width}</p>
    )
}

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

import { useState } from 'react';

function windowWidth() {
    const [width, setWithd] = useState(window.innerWidth);
    useEffect(() => {
    const handleResize = ()=>{
        setWidth(window.innerWidth);
    }
    window.addEventListener('resize', handleResize);
    }, [width]); // width 没有变化则不处理
    return (
        <p> window width is {width}</p>
    )
}

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

import { useState } from 'react';

function windowWidth() {
  const [width, setWithd] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = ()=>{
        setWidth(window.innerWidth);
    }
    window.addEventListener('resize', handleResize);

    return () => {
        // 取消监听窗口的宽度变化
        window.removeEventListener('resize');
    }
  });
  return (
      <p> window width is {width}</p>
  )
}

Как показано выше, встроенные хуки React, такие как useState и useEffect, выступают в качестве основных строительных блоков. Мы можем использовать их непосредственно в компоненте или объединить их в пользовательский хук, например useWindowWidth. Использование пользовательских хуков похоже на использование встроенного API React.

📌Пользовательские хуки пользовательских компонентов

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

Talk is cheap, show me the code.

// 一个显示目前窗口大小的组件
function responsiveComponent(){
   // custom hooks
   const width = useWindowWidth(); 
   return (
       <p>当前窗口的宽度是 {width}</p>
   )
}

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

Давайте посмотрим, как реализовать этот пользовательский хук. Мы используем собственное состояние React, чтобы сохранить текущую ширину окна, и используем побочные эффекты, чтобы установить это состояние при изменении размера окна.

import { useState, useEffect} from 'react';
// custom hooks to listen window width change
function useWindowWidth(){
    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
        const handleResize = ()=>{
            setWidth(window.innerWidth);
        }
        window.addEventListener('resize', handleResize);
    }, [width]); // width 没有变化则不处理

    return width;
}

[Пример онлайн-редактирования]

⚡ Правила для React Hooks

Хуки — это функции JavaScript, но они накладывают два дополнительных правила:

  • только вверхний этажПозвоните Хуксу. Не вызывайте хуки в циклах, условных выражениях или вложенных функциях.
  • Вызывайте хуки только из функциональных компонентов React. Не вызывайте хуки из обычных функций JavaScript. (Есть еще одно место для вызова хуков — ваши собственные хуки.)

🔌 Другие крючки

Вот несколько менее часто используемых встроенных хуков. Например, useContext позволяет вам подписываться на контексты React без вложенности:

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}

Нашел очень интересный склад,react-use, содержит много интересных пользовательских хуков

👀Как работают крючки

Далее переводится сreact-hooks-not-magic-just-arrays.

хуки реакции на самом деле просто массив, а не магия.

Как добитьсяuseState()метод

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

Сначала начнем с компонента:

function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi");
  const [lastName, setLastName] = useState("Yardley");

  return (
    <Button onClick={() => setFirstName("Fred")}>Fred</Button>
  );
}

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

Так при чем здесь React?

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

1) Инициализировать

Создайте два пустых массива:settersа такжеstate

установить курсор на 0

img
image.png

Инициализация: два пустых массива, курсор равен 0

2) Первый рендер

Запустите функцию компонента в первый раз.

Каждый вызов useState() при первом запуске помещает функцию установки (привязанную к положению курсора) в массив установок, а затем помещает некоторое состояние в массив состояний.

img
image.png

Первый рендеринг: элементы записываются в массив по мере увеличения курсора.

3) Последующий рендеринг

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

img
image.png

Последующий рендеринг: элемент, прочитанный из массива, является приращением курсора

4) Обработка событий

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

img
image.png

Сеттеры «запоминают» свой индекс и устанавливают память в соответствии с ним.

Реализация функциональности useState через псевдокод

Вот пример кода, демонстрирующий реализацию:

let state = [];
let setters = [];
let firstRun = true;
let cursor = 0;

function createSetter(cursor) {
  return function setterWithCursor(newVal) {
    state[cursor] = newVal;
  };
}

// useState的伪代码实现
export function useState(initVal) {
  if (firstRun) {
    state.push(initVal);
    setters.push(createSetter(cursor));
    firstRun = false;
  }

  const setter = setters[cursor];
  const value = state[cursor];

  cursor++;
  return [value, setter];
}

// 模拟使用useState
function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
  const [lastName, setLastName] = useState("Yardley"); // cursor: 1

  return (
    <div>
      <Button onClick={() => setFirstName("Richard")}>Richard</Button>
      <Button onClick={() => setFirstName("Fred")}>Fred</Button>
    </div>
  );
}

// 模拟Reacts渲染周期
function MyComponent() {
  cursor = 0; //  重置光标的位置
  return <RenderFunctionComponent />; // render
}

console.log(state); // Pre-render: []
MyComponent();
console.log(state); // 首次渲染: ['Rudi', 'Yardley']
MyComponent();
console.log(state); // 后续渲染: ['Rudi', 'Yardley']

// 点击'Fred' 按钮 

console.log(state); // 点击后: ['Fred', 'Yardley']

Суммировать

Хуки все еще находятся на ранней стадии, но они дают нам хорошее представление о логике повторного использования компонентов, которую вы можете испытать в react-16.7.0-alpha.0.

Связанное Чтение [Ежедневная рекомендация курса] Машинное обучение в действии! Быстрый старт бизнеса в сфере онлайн-рекламы и знание CTR

Эта статья была разрешена автором для публикации в сообществе Tencent Cloud + Для получения дополнительных оригинальных текстов, пожалуйстанажмите

Найдите и подпишитесь на общедоступную учетную запись «Сообщество Yunjia», получите технические галантереи как можно скорее и ответьте на 1024 после подписки, чтобы отправить вам подарочный пакет технических курсов!

Огромный технический практический опыт, все вСообщество Юнцзя!