1. 程式人生 > 實用技巧 >TypeScript and React: Hooks

TypeScript and React: Hooks

Hooks以前將“無狀態”功能元件放到了……基本上,傳統類元件都可以做到。使用更乾淨的API!在React 16.7中釋出後不久,DefinitelyTyped中的React型別也得到了更新。瞭解如何在TypeScript中使用鉤子!

useState

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

const Counter:FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
  const [clicks, setClicks] = useState(initial);
  return <>
    <p>Clicks: {clicks}</p>
    <button onClick={() => setClicks(clicks+1)}>+</button>
    <button onClick={() => setClicks(clicks-1)}>-</button>
  </>
}

useEffect

useEffect在這裡有所有副作用。新增事件偵聽器,更改文件中的內容,獲取資料。一切你所使用的(元件生命週期方法componentDidUpdatecomponentDidMountcomponentWillUnmount)的方法簽名是非常簡單的。它接受兩個引數:

  • 無需任何引數即可呼叫的函式。這是您要呼叫的副作用。
  • 型別的值陣列any。此引數是可選的。如果不提供,則每次元件更新時都會呼叫提供的功能。如果這樣做,React將檢查這些值是否確實發生了變化,並且僅在存在差異時才觸發函式。
useEffect(() => {
  const handler = () => {
    document.title = window.width;
  }
  window.addEventListener('resize', handler);

  return true;
  return () => {
    window.removeEventListener('resize', handler);
  }
})

useContext

useContext允許您從元件中的任何位置訪問上下文屬性。非常類似於Context.Consumer 類元件中的do。型別推斷在這裡非常出色,您不需要使用任何TypeScript特定的語言功能就可以完成所有工作:

import React, { useContext } from 'react';

export const LanguageContext = React.createContext({ lang: 'en' });

const Display = () => {
  const { lang } = useContext(LanguageContext);
  return <>
    <p>Your selected language: {lang}</p>
  </>
}

useRef

function TextInputWithFocusButton() {
  
  const inputEl = useRef<HTMLInputElement>(null);
  const onButtonClick = () => {
   
    if(inputEl && inputEl.current) {
      inputEl.current.focus();
    } 
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useMemo-useCallback

您知道useEffect,可以通過向其傳遞一些引數來影響某些函式的執行。React檢查這些引數是否已更改,並且僅在存在差異的情況下才會執行此功能。
useMemo做類似的事情。假設您有大量計算方法,並且只想在其引數更改時執行它們,而不是每次元件更新時都執行它們。useMemo返回記憶的結果,並且僅在引數更改時才執行回撥函式。

function getHistogram(image: ImageData): number[] {
  ...
  return histogram;
}

function Histogram() {
  ...
  const histogram = useMemo(() => getHistogram(imageData), [imageData]);
}

useCallback非常相似。實際上,這也是可以表達的捷徑useMemo。但是它返回一個回撥函式,而不是一個值。

const memoCallback = useCallback((a: number) => {
  // doSomething
}, [a])

useReducer

type ActionType = {
  type: 'reset' | 'decrement' | 'increment'
}

const initialState = { count: 0 };

// We only need to set the type here ...
function reducer(state, action: ActionType) {
  switch (action.type) {
    // ... to make sure that we don't have any other strings here ...
    case 'reset':
      return initialState;
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter({ initialCount = 0 }) {
  const [state, dispatch] = useReducer(reducer, { count: initialCount });
  return (
    <>
      Count: {state.count}
      { /* and can dispatch certain events here */ }
      <button onClick={() => dispatch({ type: 'reset' })}>
        Reset
      </button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}