Практика использования React-хуков

React.js

предисловие

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

текст

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

Когда выполнять операцию инициализации

Когда я перешел на хуки React, я впервые столкнулся с этой проблемой:

Вообще говоря, бизнес-компоненты часто сталкиваются со сценариями, в которых им необходимо получить бизнес-данные и выполнить операции инициализации, инициируя запросы ajax. При использовании программирования компонента класса мы можем выполнить эту операцию в функции ловушки жизненного цикла (такой как componentDidMount, конструктор и т. д.), предоставляемой компонентом класса. Однако, если после переключения на React-хуки в функциональном компоненте нет функции хука жизненного цикла, как насчет операции инициализации? Вы не можете использовать компонент класса каждый раз, когда сталкиваетесь с этим сценарием, верно?

решение:Использовать эффект(Если вы хотите узнать, что такое useEffect, вы можетекликните сюда)

useEffect, как следует из названия, предназначен для выполнения операций с побочными эффектами, вы можете думать об этом какcomponentDidMount, componentDidUpdate, and componentWillUnmountколлекция. Объявление его функции выглядит следующим образом

useEffect(effect: React.EffectCallback, inputs?: ReadonlyArray<any> | undefined)

Затем, в нашем реальном использовании, мы можем использовать это для выполнения операций инициализации. Например

import React, { useEffect } from 'react'

export function BusinessComponent() {
  const initData = async () => {
    // 发起请求并执行初始化操作
  }
  // 执行初始化操作,需要注意的是,如果你只是想在渲染的时候初始化一次数据,那么第二个参数必须传空数组。
  useEffect(() => {
    initData();
  }, []);

  return (<div></div>);
}

Следует отметить, что второй параметр useEffect здесь должен передавать пустой массив, так что это эквивалентно выполнению только в componentDidMount. Если второй параметр не передан, он эквивалентен componentDidMount и componentDidUpdate.

сделать небольшую уборку

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

решение:Используйте возвращаемое значение первого параметра useEffect

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

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

import React, { useEffect } from 'react'

export function QRCode(url, userId) {
  // 根据userId查询扫描状态
  const pollingQueryingStatus = async () => {
  }
  // 取消轮询
  const stopPollingQueryStatus = async() => {
  }

  useEffect(() => {
    pollingQueryingStatus();

    return stopPollingQueryStatus;
  }, []);

  // 根据url生成二维码
  return (<div></div>)
}

В этом случае это эквивалентно выполнению операции очистки в componentWillUnmount.

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

На самом деле для этой ситуации официалы тоже дали решение.Второй параметр useEffect является ключом к срабатыванию эффектов.Если пользователь передает второй параметр, то меняется только значение второго параметра ( а первый рендер ), эффекты срабатывают. Поэтому нам нужно только изменить приведенный выше код:

import React, { useEffect } from 'react'

export function QRCode(url, userId) {
  // 根据userId查询扫描状态
  const pollingQueryingStatus = async () => {
  }

  const stopPollingQueryStatus = async() => {
  }
  // 我们只是将useEffect的第二个参数加了个userId
  useEffect(() => {
    pollingQueryingStatus();

    return stopPollingQueryStatus;
  }, [userId]);

  // 根据url生成二维码
  return (<div></div>)
}

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

Различия между useState и setState

Хуки React используют useState вместо состояния в классе Component. Однако в конкретном процессе разработки я также обнаружил некоторые отличия. Введение useState можеткликните сюда

При setState мы можем изменять только локальные переменные в состоянии, не передавая все измененное состояние, например

import React, { PureComponent } from 'react';

export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      name: 'cjg',
      age: 18,
    }
  }

  handleClick = () => {
    const { count } = this.state;
    // 我们只需要传入修改的局部变量
    this.setState({
      count: count + 1,
    });
  }

  render() {
    return (
      <button onClick={this.handleClick}></button>
    )
  }
}

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

import React, { useState } from 'react';

export function Count() {
  const [data, setData] = useState({
    count: 0,
    name: 'cjg',
    age: 18,
  });
    
  const handleClick = () => {
    const { count } = data;
    // 这里必须将完整的state对象传进去
    setData({
      ...data,
      count: count + 1,
    })
  };

  return (<button onClick={handleClick}></button>)
}

Уменьшите ненужный рендеринг

При разработке с классом Component мы можем использоватьshouldComponentUpdateЧтобы уменьшить ненужный рендеринг, как реализовать такую ​​функцию после использования хуков реакции?

решение:React.memoиuseMemo

Для этой ситуации, конечно же, React также предлагает официальное решение, заключающееся в использовании React.memo и useMemo.

React.memo

React.momo на самом деле не является хуком, он фактически эквивалентен PureComponent, но он только сравнивает свойства. Он используется следующим образом (на примере выше):

import React, { useState } from 'react';

export const Count = React.memo((props) => {
  const [data, setData] = useState({
    count: 0,
    name: 'cjg',
    age: 18,
  });
  
  const handleClick = () => {
    const { count } = data;
    setData({
      ...data,
      count: count + 1,
    })
  };

  return (<button onClick={handleClick}>count:{data.count}</button>)
});

useMemo

Использование useMemo на самом деле немного похоже на useEffects Давайте посмотрим непосредственно на официальный пример.

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

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

Суммировать

Сначала было очень неудобно переключаться с компонентов класса на реагирующие хуки. Но когда я привыкла к этому способу письма, мое настроение было следующим:

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

Адрес этой статьи находится по адресу ->Адрес моего блога, добро пожаловать, чтобы начать или подписаться