React中10種Hook的使用介紹

嘔歐陽熱火個發表於2022-03-13

React Hook是什麼?

React官網是這麼介紹的: Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。

完全可選的 你無需重寫任何已有程式碼就可以在一些元件中嘗試 Hook。但是如果你不想,你不必現在就去學習或使用 Hook。

100% 向後相容的 Hook 不包含任何破壞性改動。

現在可用 Hook 已釋出於 v16.8.0。

沒有計劃從 React 中移除 class 你可以在本頁底部的章節讀到更多關於 Hook 的漸進策略。

Hook 不會影響你對 React 概念的理解 恰恰相反,Hook 為已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命週期。稍後我們將看到,Hook 還提供了一種更強大的方式來組合他們。

如果對react還不夠了解建議先看下react官方文件,寫寫demo再來看文章,因為有的react基礎的東西我就一筆帶過不細說。
react 官方文件 

React目前提供的Hook

hook 用途
useState 設定和改變state,代替原來的state和setState
useEffect 代替原來的生命週期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合併版
useLayoutEffect 與 useEffect 作用相同,但它會同步呼叫 effect
useMemo 控制元件更新條件,可根據狀態變化控制方法執行,優化傳值
useCallback useMemo優化傳值,usecallback優化傳的方法,是否更新
useRef 跟以前的ref,一樣,只是更簡潔了
useContext 上下文爺孫及更深元件傳值
useReducer 代替原來redux裡的reducer,配合useContext一起使用
useDebugValue 在 React 開發者工具中顯示自定義 hook 的標籤,除錯使用。
useImperativeHandle 可以讓你在使用 ref 時自定義暴露給父元件的例項值。

1.useState

import React from 'react';
import './App.css';
//通常的class寫法,改變狀態
class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      hook:'react hook 是真的好用啊'
    }
  }
  changehook = () => {
    this.setState({
      hook:'我改變了react hook 的值'
    })
  }
  render () {
    const { hook } = this.state
    return(
         <header className="App-header">
          {hook}
          <button onClick={this.changehook}>
            改變hook
          </button>
        </header>
      )
  }
}
export  {App}
 
//函式式寫法,改變狀態
function App() {
//建立了一個叫hook的變數,sethook方法可以改變這個變數,初始值為‘react hook 是真的好用啊'
 const [hook, sethook] = useState("react hook 是真的好用啊");
  return ( 
    <header className="App-header">
      {hook}{/**這裡的變數和方法也是可以直接使用的 */}
      <button onClick={() => sethook("我改變了react hook 的值")}>
        改變hook
      </button>
    </header>
  );
}
export  {App}
 
//箭頭函式的函式寫法,改變狀態
export const App = props => {
  const [hook, sethook] = useState("react hook 是真的好用啊");
  return (
    <header className="App-header">
      {hook}
      <button onClick={() => sethook("我改變了react hook 的值")}>
        改變hook
      </button>
    </header>
  );

使用方法備註在上面的demo中
看完上面useState的對比使用,一個小的demo結構更清晰,程式碼更簡潔,更像寫js程式碼,運用到專案中,那豈不是美滋滋。

2.useEffect & useLayoutEffect

useEffect代替原來的生命週期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合併版
useEffect( ()=>{ return ()=>{ } } , [ ])

  • 第一個引數,是函式,預設第一次渲染和更新時都會觸發,預設自帶一個return ,return一個函式表示可以再銷燬之前可以處理些事情
  • 第二個引數,陣列【】,空的時候表示只執行一次,更新時不觸發,裡面的引數是什麼,當引數變化時才會執行useEffect
    • useEffect可以多次使用,按照先後順序執行
    • useLayoutEffect 強制useeffect的執行為同步,並且先執行useLayoutEffect內部的函式
import React, { useState, useEffect, useLayoutEffect } from 'react';
 
//箭頭函式的寫法,改變狀態
const UseEffect = (props) => {
 //建立了一個叫hook的變數,sethook方法可以改變這個變數,初始值為‘react hook 是真的好用啊'
 const [ hook, sethook ] = useState('react hook 是真的好用啊');
 const [ name ] = useState('baby張');
 return (
  <header className="UseEffect-header">
   <h3>UseEffect</h3>
   <Child hook={hook} name={name} />
   {/**上面的變數和下面方法也是可以直接使用的 */}
   <button onClick={() => sethook('我改變了react hook 的值' + new Date().getTime())}>改變hook</button>
  </header>
 );
};
 
const Child = (props) => {
 const [ newhook, setnewhook ] = useState(props.hook);
 //這樣寫可以代替以前的componentDidMount,第二個引數為空陣列,表示該useEffect只執行一次
 useEffect(() => {
  console.log('first componentDidMount');
 }, []);
 
 //第二個引數,陣列裡是hook,當hook變化時,useEffect會觸發,當hook變化時,先銷燬再執行第一個函式。
 useEffect(
  () => {
   setnewhook(props.hook + '222222222');
   console.log('useEffect');
   return () => {
    console.log('componentWillUnmount ');
   };
  },
  [ props.hook ]
 );
 
 //useLayoutEffect 強制useeffect的執行為同步,並且先執行useLayoutEffect內部的函式
 useLayoutEffect(
  () => {
   console.log('useLayoutEffect');
   return () => {
    console.log('useLayoutEffect componentWillUnmount');
   };
  },
  [ props.hook ]
 );
 
 return (
  <div>
   <p>{props.name}</p>
   {newhook}
  </div>
 );
};
 
export default UseEffect;

3.useMemo & useCallback

他們都可以用來優化子元件的渲染問題,或者監聽子元件狀態變化來處理事件,這一點在以前是很難做到的,因為shouldComponentUpdate 裡能監聽到是否變化,但沒法控制其他的外部方法,只能返回true和false,而componentDidUpdate只能在更新後執行,所以想在渲染之前做些事情就不好搞了。
useCallback目前還不能用

import React, { useState, useMemo } from 'react';
 
const Child = ({ age, name, children }) => {
    //在不用useMemo做處理的時候,只要父元件狀態改變了,子元件都會渲染一次,用了useMemo可以監聽某個狀態name,當name變化時候執行useMemo裡第一個函式
    console.log(age, name, children, '11111111');
 function namechange() {
  console.log(age, name, children, '22222222');
  return name + 'change';
    }
     {/** react 官網雖說useCallback與useMemo的功能差不多,但不知道版本問題還怎麼回是,這個方法目前還不能用
    const memoizedCallback = useCallback(
        () => {
            console.log('useCallback')
        },
        [name],
      );
    console.log(memoizedCallback,'memoizedCallback')
     */}
    //useMemo有兩個引數,和useEffect一樣,第一個引數是函式,第二個引數是個陣列,用來監聽某個狀態不變化
 const changedname = useMemo(() => namechange(), [ name ]);
 return (
  <div style={{ border: '1px solid' }}>
   <p>children:{children}</p>
   <p>name:{name}</p>
   <p>changed:{changedname}</p>
   <p>age:{age}</p>
  </div>
 );
};
 
const UseMemo = () => {
    //useState 設定名字和年齡,並用2兩個按鈕改變他們,傳給Child元件
 const [ name, setname ] = useState('baby張'); 
 const [ age, setage ] = useState(18);
 return (
  <div>
   <button
    onClick={() => {
     setname('baby張' + new Date().getTime()); 
    }}
   >
    改名字
   </button>
   <button
    onClick={() => {
     setage('年齡' + new Date().getTime());
    }}
   >
    改年齡
   </button>
   <p>
    UseMemo {name}:{age}
   </p>
   <Child age={age} name={name}>
    {name}的children
   </Child>
  </div>
 );
};
 
export default UseMemo;

4.useRef

ref跟之前差不多,useRef建立–繫結–使用,三步走,詳細看程式碼以及備註

import React, { useState, useRef } from 'react';
 
const UseRef = () => {
 //這裡useState繫結個input,關聯一個狀態name
 const [ name, setname ] = useState('baby張');
 const refvalue = useRef(null);// 先建立一個空的useRef
 function addRef() {
  refvalue.current.value = name;   //點選按鈕時候給這個ref賦值
  // refvalue.current = name  //這樣寫時,即使ref沒有繫結在dom上,值依然會存在建立的ref上,並且可以使用它
  console.log(refvalue.current.value);
 }
 return (
  <div>
            <input
                defaultValue={name}
    onChange={(e) => {
     setname(e.target.value);
                }}
   />
   <button onClick={addRef}>給下面插入名字</button>
   <p>給我個UseRef名字:</p>
   <input ref={refvalue} />
  </div>
 );
};
 
export default UseRef;

5.useContext

之前使用過context的小夥伴一看就懂,useContext的話跟之前的context基本用法差不多,程式碼內有詳細註釋說明,建立,傳值,使用

import React, { useState, useContext, createContext } from 'react';
 
const ContextName = createContext();
//這裡為了方便寫部落格,爺爺孫子元件都寫在一個檔案裡,正常需要在爺爺元件和孫子元件挨個引入建立的Context
 
const UseContext = () => {
 //這裡useState建立一個狀態,並按鈕控制變化
 const [ name, setname ] = useState('baby張');
 return (
  <div>
   <h3>UseContext 爺爺</h3>
   <button
    onClick={() => {
     setname('baby張' + new Date().getTime());
    }}
   >
    改變名字
   </button>
   {/**這裡跟context用法一樣,需要provider向子元件傳遞value值,value不一定是一個引數 */}}
   <ContextName.Provider value={{ name: name, age: 18 }}>
    {/**需要用到變數的子元件一定要寫在provider中間,才能實現共享 */}
    <Child />
   </ContextName.Provider>
  </div>
 );
};
 
const Child = () => {
 //建立一個兒子元件,裡面引入孫子元件
 return (
  <div style={{ border: '1px solid' }}>
   Child 兒子
   <ChildChild />
  </div>
 );
};
 
const ChildChild = () => {
 //建立孫子元件,接受爺爺元件的狀態,用useContext,獲取到爺爺元件建立的ContextName的value值
 let childname = useContext(ContextName);
 return (
  <div style={{ border: '1px solid' }}>
   ChildChild 孫子
   <p>
    {childname.name}:{childname.age}
   </p>
  </div>
 );
};
 
export default UseContext

6.useReducer

這裡的usereducer會返回state和dispatch,通過context傳遞到子元件,然後直接呼叫state或者觸發reducer,我們常用useReducer 與useContext createContext一起用,模擬reudx的傳值和重新賦值操作。

import React, { useState, useReducer, useContext, createContext } from 'react';
 
//初始化stroe的型別、初始化值、建立reducer
const ADD_COUNTER = 'ADD_COUNTER';
const initReducer = {
 count: 0
};
//正常的reducer編寫
function reducer(state, action) {
 switch (action.type) {
  case ADD_COUNTER:
   return { ...state, count: state.count + 1 };
  default:
   return state;
 }
}
 
const CountContext = createContext();
//上面這一段,初始化state和reducer建立context,可以單獨寫一個檔案,這裡為了方便理解,放一個檔案裡寫了
 
const UseReducer = () => {
 const [ name, setname ] = useState('baby張');
 //父元件裡使用useReducer,第一個引數是reducer函式,第二個引數是state,返回的是state和dispash
 const [ state, dispatch ] = useReducer(reducer, initReducer);
 return (
  <div>
   UseReducer
   {/* 在這裡通過context,講reducer和state傳遞給子元件*/}
   <CountContext.Provider value={{ state, dispatch, name, setname }}>
    <Child />
   </CountContext.Provider>
  </div>
 );
};
 
const Child = () => {
 //跟正常的接受context一樣,接受父元件的值,通過事件等方式觸發reducer,實現redux效果
 const { state, dispatch, name, setname } = useContext(CountContext);
 function handleclick(count) {
  dispatch({ type: ADD_COUNTER, count: 17 });
  setname(count % 2 == 0 ? 'babybrother' : 'baby張');
 }
 return (
  <div>
   <p>
    {name}今年{state.count}歲
   </p>
   <button onClick={() => handleclick(state.count)}>長大了</button>
  </div>
 );
};
 
export default UseReducer;

上github地址 10個hook demo 點一點star,謝謝咯!

github地址:

到此這篇關於React中10種Hook的使用介紹的文章就介紹到這了,更多相關React Hook內容請搜尋指令碼之家以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援指令碼之家!

您可能感興趣的文章:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70015113/viewspace-2869936/,如需轉載,請註明出處,否則將追究法律責任。

相關文章