🔱 Быстро начните работу с тремя базовыми хуками React

React.js

HooksЕго давно нет, интересно, начали ли вы его использовать в проекте❓ Если вы не разбираетесь в детской обуви, можете прочитать эту статью и сравнить три основыHooksи традицииclassОтличие и использование компонентов😙

Три основы, о которых мы говоримHooksДа:

  • useStateПоддерживается внутри функциональных компонентовstate
  • useEffectВызов с побочными эффектами внутри функционального компонента аналогичен вызовуcomponentDidMount,componentDidUpdateпохожие, но разные
  • useContextМониторинг изменений обновлений провайдера

useState

useStateпозволяет нам поддерживать в функциональных компонентахstate, традиционный подход требует использования компонентов класса. Например🌰, нам нужно поле ввода.По мере изменения содержимого поля ввода,labelСодержимое, отображаемое меткой, также изменяется одновременно. Вот два разных способа письма:

не используйте useState:

import React from "react";
// 1
export class ClassTest extends React.Component {
  // 2
  state = {
    username: this.props.initialState
  }
  // 3
  changeUserName(val) {
    this.setState({ username: val })
  }
  // 4
  render() {
    return (
      <div>
        <label style={{ display: 'block' }} htmlFor="username">username: {this.state.username}</label>
        <input type="text" name="username" onChange={e => this.changeUserName(e.target.value)} />
      </div>
    )
  }
}
  1. Нам нужно определить класс и начатьReact.ComponentУнаследовано
  2. Также необходимо инициализироватьstate
  3. Инициализировать измененияstateМетоды
  4. Наконец используйтеrenderвозврат функцииJSX

✅Используйте состояние использования:

// 1
import React, { useState } from "react";

export function UseStateTest({ initialState }) {
  // 2
  let [username, changeUserName] = useState(initialState)
  // 3
  return (
    <div>
      <label style={{ display: 'block' }} htmlFor="username">username: {username}</label>
      <input type="text" name="username" onChange={e => changeUserName(e.target.value)} />
    </div>
  )
}

В родительском компоненте используйте:

import React from "react";
// 引入组件
import { UseStateTest } from './components/UseStateTest'

// 4
const App = () => (
  <div>
    <UseStateTest initialState={'initial value'} />
  </div>
)

export default App;
  1. нужно отreactвведен вuseStateэто 📦
  2. использоватьuseStateметод, который получает параметр инициализации, определяетstateпеременные и изменяющиесяstateМетоды
  3. Используйте его непосредственно там, где вам это нужноstateЭтой переменной достаточно, добавив обработчик события, чтобы вызвать изменениеstateМетоды
  4. Вызывается в родительском компоненте черезpropsпередачаinitialStateзначение инициализации

использоватьuseStateметод замены оригиналаclassМало того, что улучшится производительность, вы увидите гораздо меньше кода и вам больше не нужно будет использоватьthis, поэтому он может поддерживатьstateФункциональные компоненты действительно приятны в использовании 😀

  • class classTest extends React.Components {}🔜function UseStateTest(props) {}Написание функционального компонента
  • this.state.username🔜usernameиспользоватьstateненужныйthis
  • this.setState({ username: '' })🔜changeUserName('')Изменятьstateнет необходимости писатьsetStateметод

Описание документации: https://zh-hans.reactjs.org/docs/hooks-state.html

useEffect

useEffectОн предназначен для обработки побочных эффектов, таких как выборка данных, создание подписок, ручное изменение DOM и т. д. ты можешь представить, что этоcomponentDidMountа такжеcomponentDidUpdateа такжеcomponentWillUnmountкомбинация.

В качестве примера 🌰🌰 допустим, мы создаемdivтеги, которые отправляются при каждом нажатииhttpзапрос и страницаtitleИзменить на соответствующее значение:

import React from 'react'
// 1
import { useState, useEffect } from 'react'

export function UseEffectTest() {
    let [msg, changeMsg] = useState('loading...')
    // 2
    async function getData(url) { // 获取 json 数据
        return await fetch(url).then(d => d.json())
    }
    // 3
    async function handleClick() { // 点击事件改变 state
        let data = await getData('https://httpbin.org/uuid').then(d => d.uuid)
        changeMsg(data)
    }
    // 4
    useEffect(() => { // 副作用
        document.title = msg
    })
    return (
        <div onClick={() => handleClick()}>{msg}</div>
    )
}
  1. Первый изreactвведен вuseEffect😳
  2. Затем создайте выборку данныхgetDataметод
  3. Создайте обработчик событийhandleClick
  4. использоватьuseEffectОбработка побочных эффектов: изменение страницыtitle

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

import React from 'react'
// 1
export class ClassTest extends React.Component {
    // 2
    state = {
        msg: 'loading...'
    }
    // 3
    async getData(url) { // 获取 json 数据
        return await fetch(url).then(d => d.json())
    }
    handleClick = async () => { // 点击事件改变 state
        let data = await this.getData('https://httpbin.org/uuid').then(d => d.uuid)
        this.setState({ msg: data })
    }
    // 4
    componentDidMount() {
        document.title = this.state.msg
    }
    componentDidUpdate() {
        document.title = this.state.msg
    }
    // 5
    render() {
        return (
            <div onClick={this.handleClick}>{this.state.msg}</div>
        )
    }
}
  1. Сначала создайте классClassTest
  2. инициализацияstate
  3. Определение методов получения данных и обработчиков событий
  4. существуетcomponentDidMountа такжеcomponentDidUpdateсмена сценыdocument.title
  5. наконец прошлоrenderрендеринг функции

Все заснули после написания всего этого 💤

Использование useEffect не только убирает некоторые ненужные вещи, но и объединяетcomponentDidMountа такжеcomponentDidUpdateметод, в котором код нужно написать только один раз. 😀

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

См. документацию: https://zh-hans.reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects.

Кроме того, на официальном сайте также приводится пример подписки на клиринг подписки:

20190313113615.png

использоватьuseEffectнепосредственныйreturnФункция будет делать:

20190313113627.png

Возвращаемая функция является необязательной и может использоваться или не использоваться:

20190313113753.png

Документация: https://zh-hans.reactjs.org/docs/hooks-effect.html#recap

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

useEffect(() => {
    window.addEventListener('keydown', handleKeydown);
    return () => {
        window.removeEventListener('keydown', handleKeydown);
    }
})

useContext

useContextСамое большое изменение заключается в том, что вы можете использоватьConsumerпри упаковкеChildrenТеперь предположим, что мы сначала создаем контекст, в котором есть файл с именемusernameизstate, и модификацияusernameМетодыhandleChangeUsername

создать контекст

Без состояния использования:

Не используйтеstate hooksКод выглядит следующим образом:

import React, { createContext } from 'react'

// 1. 使用 createContext 创建上下文
export const UserContext = new createContext()

// 2. 创建 Provider
export class UserProvider extends React.Component {

    handleChangeUsername = (val) => {
        this.setState({ username: val })
    }

    state = {
        username: '',
        handleChangeUsername: this.handleChangeUsername
    }

    render() {
        return (
            <UserContext.Provider value={this.state}>
                {this.props.children}
            </UserContext.Provider>
        ) 
    }
}

// 3. 创建 Consumer
export const UserConsumer = UserContext.Consumer

Посмотрите, что мы сделали:

  1. Сначала мы используемcreateContextсозданный контекст
  2. Затем мы создаемProvider, который определяетhandleChangeUsernameМетоды иusernameизstate, и возвращает пакетthis.props.childrenизProvider
  3. Наконец мы возвращаемсяUserContext.Consumer

Код более подробный, вы можете использовать вышеупомянутыйuseStateУпростите это:

✅ Используйте состояние использования:

использоватьstate hooks:

import React, { createContext, useState } from 'react'

// 1. 使用 createContext 创建上下文
export const UserContext = new createContext()

// 2. 创建 Provider
export const UserProvider = props => {
    let [username, handleChangeUsername] = useState('')
    return (
        <UserContext.Provider value={{username, handleChangeUsername}}>
            {props.children}
        </UserContext.Provider>
    )
}

// 3. 创建 Consumer
export const UserConsumer = UserContext.Consumer

использоватьuseStateСоздание контекста более лаконично.

использовать контекст

После определения контекста давайте рассмотрим использованиеuseContextи не использоватьuseContextВ чем разница 🎁:

Без использования контекста:

import React  from "react";
import { UserConsumer, UserProvider } from './UserContext'

const Pannel = () => (
  <UserConsumer>
    {/* 不使用 useContext 需要调用 Consumer 包裹 children */}
    {({ username, handleChangeUsername }) => (
      <div>
        <div>user: {username}</div>
        <input onChange={e => handleChangeUsername(e.target.value)} />
      </div>
    )}
  </UserConsumer>
)

const Form = () => <Pannel></Pannel>

const App = () => (
  <div>
    <UserProvider>
      <Form></Form>
    </UserProvider>
  </div>
)

export default App;

✅ Используйте useContext:

просто импортироватьUserContext,использоватьuseContextМетод может быть:

import React, { useContext }  from "react"; // 1
import { UserProvider, UserContext } from './UserContext' // 2

const Pannel = () => {
  const { username, handleChangeUsername } = useContext(UserContext) // 3
  return (
    <div>
      <div>user: {username}</div>
      <input onChange={e => handleChangeUsername(e.target.value)} />
    </div>
  )
}

const Form = () => <Pannel></Pannel>

// 4
const App = () => (
  <div>
    <UserProvider>
      <Form></Form>
    </UserProvider>
  </div>
)

export default App;

Посмотрите, что было сделано:

  1. Представить первымuseContext
  2. затем импортироватьUserProviderи контекстUserContext
  3. Затем вызовите его в компоненте, который необходимо использовать.useContextспособ получитьstate
  4. Конечно, предполагается использовать его в родительском компоненте.UserProviderвложенный мастерchildren

так черезuseContextа такжеuseStateРефакторинг завершен, и кажется, что кода стало намного меньше 😄

выше, три основныхHooksВведение закончено, и вот как можно приступить к работе.Функциональные компоненты иHooksЭто действительно здорово использовать вместе⛄

Ссылаться на:

  • https://codeburst.io/quick-intro-to-react-hooks-6dd8ecb898ed
  • https://reactjs.org/docs/hooks-reference.html