Manon.icu

I'm here to make you a better developer by teaching you everything I know about building for the web.

Published 2021-04-22

React Hooks

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

  • useState
  • useEffect
  • useRef
  • useContext
  • useCallback
  • useMemo

使用 useState

useState 可以让你在不编写 class 的情况下使用 state。

import {useState} from 'react'

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

  function updateCount() {
    setCount(count + 1)
  }

  return <button onClick={updateCount}>Count is: {count}</button>
}

useState第一个参数是初始值,第二个参数是一个函数,这个函数可以更新初始值。

如果更新函数返回值与初始值相同,那么组件不会更新。否则将组件的重新渲染加入队列。

使用 useEffect

useEffect(callback[, dependencies]);

  • callback是包含副作用逻辑的函数
  • dependencies是一个数组,表示依赖的数据发生变化时,callback函数才会执行。

k6ZFjw

dependecies未提供时,每次渲染都会执行callback函数。

dependencies提供的是一个空数组时,callback函数只会执行一次。

dependencies提供的是一个不为空的数组时,callback函数会在依赖的数据发生变化时执行。

import {useEffect} from 'react'

function MyComponent() {
  useEffect(() => {
    // perform side effect here
  }, [])
}

A Simple Explanation of React.useEffect()

使用 useRef

useRef允许直接访问 JSX 元素的 DOM 元素。

import {useRef} from 'react'

function MyComponent() {
  const ref = useRef()

  return <div ref={ref} />
}

此时,可以使用ref.current访问到 DOM 元素。比如:

import {useWindowEvent} from '@mantine/hooks'
import {useRef} from 'react'

function Header() {
  const inputRef = useRef()

  useWindowEvent('keydown', (event) => {
    if (event.code === 'KeyK' && event.ctrlKey) {
      event.preventDefault()
      inputRef.current.focus()
    }
  })

  return <input ref={inputRef} />
}

使用 useContext

useContext提供比Context.Consumer更简单的方式来访问 Context。比如:

import { createContext, useContext } from 'react';

const NameContext = createContext('');

function App() {
  return (
    <NameContext.Provider value="John Doe">
      <Body />
    <NameContext.Provider>
  );
}

function Body() {
  return <Greeting />;
}

function Greeting() {
	const name = useContext(NameContext);

  return (
    <h1>Welcome, {name}</h1>
  );
}

使用 useCallback

useCallback返回一个 memoized 函数,这个函数会在组件的每次渲染时被调用。

useCallback(fn,deps),类似于 vue 中的 computed

function App() {
  const [player, setPlayer] = React.useState('')
  const [players, setPlayers] = React.useState(['Messi', 'Ronaldo', 'Laspada'])

  function handleChangeInput(event) {
    setPlayer(event.target.value)
  }
  function handleAddPlayer() {
    setPlayers(players.concat(player))
  }
  const handleRemovePlayer = useCallback(
    (player) => {
      setPlayers(players.filter((p) => p !== player))
    },
    [players]
  )

  return (
    <>
      <input onChange={handleChangeInput} />
      <button onClick={handleAddPlayer}>Add Player</button>
      <PlayerList players={players} handleRemovePlayer={handleRemovePlayer} />
    </>
  )
}

function PlayerList({players, handleRemovePlayer}) {
  return (
    <ul>
      {players.map((player) => (
        <li key={player} onClick={() => handleRemovePlayer(player)}>
          {player}
        </li>
      ))}
    </ul>
  )
}

使用 useMemo

useMemo返回一个 memoized 值,与useEffectuseCallback类似,接收函数和依赖项作为参数。

import * as React from 'react'
import {getMDXComponent} from 'mdx-bundler/client'

function Post({code, frontmatter}) {
  const Component = React.useMemo(() => getMDXComponent(code), [code])

  return (
    <>
      <header>
        <h1>{frontmatter.title}</h1>
        <p>{frontmatter.description}</p>
      </header>
      <main>
        <Component />
      </main>
    </>
  )
}

Comments

No Comments!