Все, что вам нужно знать о React Hooks

внешний интерфейс React.js
Все, что вам нужно знать о React Hooks

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

In computer programming, the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a hook.

С точки зрения непрофессионала, Hook — это технология, которая расширяет исходные функции за счет перехвата программных и системных вызовов внутренних функций и обмена сообщениями. И какие функции React Hooks хочет улучшить? Представьте, что у вас в проекте уже есть куча компонентов, каждый из которых имеет свое состояние. Затем, когда вы захотите повторно использовать какую-то конкретную логику с отслеживанием состояния, вам придется значительно реорганизовать свое приложение. Теперь с React Hooks вам нужно только абстрагировать логический код с отслеживанием состояния, тогда их можно будет лучше использовать повторно, а независимый код будет легче тестировать и управлять им. С помощью React Hooks вы можете реализовать в функциональных компонентах все, что вы можете делать в компонентах с отслеживанием состояния, и вы можете более гибко реализовывать код своего приложения.

Далее давайте посмотрим, как React Hooks используются в реальных проектах.

государственное управление

Для бизнес-компонентов управление состоянием определенно неизбежно. В прошлом мы обычно писали компоненты класса для управления бизнес-логикой или использовали избыточность для глобального управления состоянием. Теперь мы можем воспользоваться недавно предоставленными React Hooks.State HookДля обработки состояния тех компонентов класса, которые были написаны, мы также можем использоватьState HookПосле рефакторинга давайте посмотрим на следующий код:

import React from 'react';
class Person extends React.Component {
  constructor(props) {
      super(props);
      this.state = {
          username: "scq000"
      };
  }
  
  render() {
      return (
        <div>
            <p>Welcome to homepage. {state.username}</p>
            <input type="text" placeholder="input a username" onChange={(event) => this.setState({ username: event.target.value)})}></input>
        </div>
      );
  }
}

Затем попробуйте преобразовать его в функциональный компонент:

import React, {useState} from 'react';

export const Person = () => {
  const [state, setState] = useState({username: "scq000"});
  
  return (
  	<div>
  		<p>Welcome to homepage. {state.username}</p>
		<input type="text" placeholder="input a username" onChange={(event) => setState({username: event.target.value})}></input>
  	</div>
  )
}

Как и в приведенном выше коде, мы сначала используемuseStateAPI для объявления внутреннего состояния, за которым следует новая переменная состоянияstateи его метод установки. Здесь, чтобы уменьшить нагрузку на рефакторинг, я сознательно выбралstateС этим именем переменной вы также можете извлекать и использовать каждое независимое состояние отдельно, например, используя кодconst [username, setUsername] = userState("scq000"). Внутри последующих компонентов мы можем использовать это внутреннее состояние для обработки бизнес-логики. Из-за способа написания функциональных компонентов мы также можем избежать многих этих привязок, и эту часть логики также можно извлечь и повторно использовать в последующем процессе использования. Однако здесь есть одно замечание:Когда вы используете метод set, старое состояние не объединяется автоматически с новым состоянием., поэтому, если извлеченное состояние является объектом с несколькими свойствами, для обновления состояния необходимо использовать следующий синтаксис:

setState({
    ...state,
  	username: event.target.value
});

управление жизненным циклом

Все мы знаем, что управление жизненным циклом компонентов — это душа всего реактивного компонента. Используя функции жизненного цикла, мы можем контролировать загрузку, обновление и выгрузку всего компонента. Доступно в React HooksEffectХуки, которые позволяют реализовать эти функции в функциональных компонентах.

Чтобы понять, я продемонстрирую, как использовать его отдельно.EffectХуки реализуют различные методы жизненного цикла изначально в компоненте класса. Следующий код представляет собой компонент Class, с которым мы знакомы:

import React from 'react';
class Person extends React.Component {
  constructor(props) {
      super(props);
      this.state = {
          username: "scq000"
      };
  }
  
  componentDidMount() {
      console.log('componentDidMount: 组件加载后')
  }
  
  componentWillUnmount() {
      console.log('componentWillUnmount: 组件卸载, 做一些清理工作')
  }
  
  componentDidUpdate(prevProps, prevState) {
      if(prevState.username !== this.state.username) {
          console.log('componentDidUpdate: 更新usernmae')
      }
  }
  
  render() {
      return (
        <div>
            <p>Welcome to homepage. {state.username}</p>
            <input type="text" placeholder="input a username" onChange={(event) => this.setState({ username: event.target.value)})}></input>
        </div>
      );
  }
}

Теперь мы используемEffectРефакторинг:

import React, {useState, useEffect} from 'react';

export const Person = () => {
  const [state, setState] = useState({username: "scq000"});
  
  useEffect(() => {
      console.log('componentDidMount: 组件加载后')
      return () => {
      	console.log('componentWillUnmount: 组件卸载, 做一些清理工作')
      }
  }, []);
  
  useEffect(() => {
      console.log('componentDidUpdate: 更新usernmae')
  }, [state.username]);
  
  return (
  	<div>
  		<p>Welcome to homepage. {state.username}</p>
		<input type="text" placeholder="input a username" onChange={(event) => setState({username: event.target.value})}></input>
  	</div>
  )
}

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

Во время использованияuseEffectМетод должен передавать два параметра, первый параметр — это функция обратного вызова: эта функция обратного вызова будет выполняться после каждого рендеринга компонента, включая первоначальный рендеринг и каждое обновление. Другим параметром является зависимость состояния (в виде массива).Как только будет обнаружено изменение данных зависимости, компонент будет обновлен, и функция обратного вызова будет выполнена снова для достиженияcomponentDidUpdateфункция. Если вы передаете пустую зависимость, вы можете получить оригиналcomponentDidMountэффект, то есть он будет выполнен только один раз. Если функция обратного вызова возвращает замыкание, возвращенная функция замыкания будет выполнена до повторного рендеринга компонента, поэтому вы можете выполнить некоторые операции очистки в этом месте, чтобы достичьcomponentWillUnmountфункция.

Также обратите внимание, чтоcomponentWillMountа такжеcomponentWillUpdateДва метода жизненного цикла устарели в новой версии React. По конкретным причинам см.здесь.

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

Пользовательский крючок

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

Инкапсулировать пользовательский хук на самом деле очень просто, то есть обернуть пользовательскую функцию, а затем объединить ее состояние с соответствующей функцией в соответствии с функцией.effectЛогика заключена в:

export const useFetch = (url, dependencies) => {
    const [isLoading, setIsLoading] = useState(false);
    const [response, setResponse] = useState(null);
  	const [error, setError] = useState(null);
  	
  	useEffect(() => {
      	setIsLoading(true);
        axios.get(url).then((res) => {
            setIsLoading(false);
            setResponse(res);
        }).catch((err) => {
            setIsLoading(false);
            setError(err);
        });
    }, dependencies)
    
  	return [isLoading, response, error];
}

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

export const Person = () => {
  const [isLoading, response, error] = useFetch("http://example.com/getPersonInfo", []); 
  
  return (
  	<div>
  		{isLoading ? 
  			<div>loading...</div>
  			:
  			(
  				error ? <div> There is an error happened. {error.message} </div>
  					  : <div> Welcome, {response.userName} </div>
  			)
  		}
  	</div>
  )
}

Меры предосторожности

В процессе использования хуков следует отметить два момента:

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

  • Хуки можно использовать только в функциональных компонентах React или в пользовательских хуках.

Чтобы мы не нарушили эти правила непреднамеренно, вы можете установить плагин eslint:

npm install eslint-plugin-react-hooks --save-dev

и используйте его в файле конфигурации:

{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}

Таким образом, как только вы нарушите эти принципы, вы получите соответствующие подсказки.

Суммировать

В этой статье рассказывается, как использовать React Hooks, и демонстрируется, как управлять состоянием и жизненным циклом функциональных компонентов на нескольких простых примерах. Официальный в настоящее время предоставляет множество базовых хуков, таких как useContext, useReducer, useMemo и т. д., которые вы можете использовать в своем проекте по мере необходимости.

использованная литература

https://reactjs.org/docs/hooks-reference.html

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

微信扫描二维码,关注我的公众号
Наконец, приглашаю всех обратить внимание на мой официальный аккаунт и вместе учиться и общаться.