REACT Hooks

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

注意事項:

  1. 只能在函數最外層調用Hook,不要再循環、條件判斷或者子函數中調用
  2.  只能在React的函數組件中調用Hook,不要在其他JS函數中調用

目錄

 

useState

性能優化useCallback


useState

  • 通過在函數組件中調用它來給組件添加一些內部state;
  • React會在重複渲染時保留這個state;
  • useState唯一的參數就是初始state;

useState會返回一對值,當前狀態和一個讓你更新它的函數,你可以在事件處理函數中或者其他地方調用這個函數,它類似class組件中的this.setState,但是它不會把新的state和舊的state進行合併。

  • 在初始渲染期間,返回的狀態(state)與傳入的第一個參數(initialState)值相同
  • setState函數用於更新state,它接收一個新的state值並將組件的一次重新渲染加入隊列

特徵:

  1. 每次渲染都是獨立的閉包
  2. 每次渲染都有它自己的props and state
  3. 每次渲染都有它自己的事件處理函數
  4. alert會捕獲當前觸發時的狀態,不會再打印更新的state (原因:每次更新state會重新render組件)
function Counter(){
    const [number,setNumber] = usestate(0);
    const alertNumber = ()=>{
        setTimeout(()=>{
            alert(number)
        },3000)
    }
    
    return (
        <>
            <p>{number}</p>
            <button onClick={()=>setNumber(number+1)}>+</button>
            <button onClick={alertNumber}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

使用函數式更新可以解決問題

function Counter(){
    const [number,setNumber] = usestate(0);
    const alertNumber = ()=>{
        setTimeout(()=>{
            //如果這裏寫的函數,state就會一直以最新的狀態往上加
            setNumber(number=>({number:number+1}));
            alert(number);
        },3000)
    }
    
    return (
        <>
            <p>{number}</p>
            <button onClick={()=>setNumber(number+1)}>+</button>
            <button onClick={alertNumber}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

 5. 惰性初始state

  • initialState初始狀態參數只會有組件初始渲染的時候調用,後續渲染會被忽略
  • 跟類組件setState不同,使用useState更新state不會自動合併,更新的時候需要傳入完整的值
let [state, setState] = useSate({number:0});
//....更新state時....
setState({...state,number:number+1})

useCallback性能優化

特性:更新useState時,如果state沒有變化組件不會刷新

爲了減少每次刷新state的渲染次數,我們可以使用useCallback,參數:fn和deps

  • fn:執行的函數
  • deps:依賴的變量,數組格式,只有在這個變量發生變化的時候纔會重新生成useCallback裏傳入的函數
function Counter(){
    const [number,setNumber] = usestate(0);
    const [name,setName] = usestate('tiya');
    const addNumber =  useCallback(setNumber(number+1),[name]);
    const addName =  useCallback(setName('bella'),[name]);
    return (
        <>
            <p>{number}</p>
            <p>{name}</p>
            <button onClick={addNumber}>+</button>
            <button onClick={()=>{
                addName('bella') 
            }}>alert</button>
        </>
    )
}
ReactDOM.render(<Counter/>,document.getElementbyId('root'));

useMemo性能優化

參數:fn和deps

  • fn:執行的函數,即官網(下文)說的--“創建”函數
  • deps:依賴的變量,數組格式,只有在這個變量發生變化的時候纔會重新生成useMemo裏傳入的函數

注意:

把“創建”函數和依賴項數組作爲參數傳入 useMemo,它僅會在某個依賴項改變時才重新計算 memoized 值。這種優化有助於避免在每次渲染時都進行高開銷的計算。

記住,傳入 useMemo 的函數會在渲染期間執行。請不要在這個函數內部執行與渲染無關的操作,諸如副作用這類的操作屬於 useEffect 的適用範疇,而不是 useMemo

如果沒有提供依賴項數組,useMemo 在每次渲染時都會計算新的值。

依賴項數組不會作爲參數傳給“創建”函數。未來也許有可能

// 案例
import React,{useState,useCallback,memo,useMemo} from 'react';
import ReactDOM from 'react-dom';

function Child(props){
  console.log('render Child');
  return (
    <button onClick={props.addClick}>{props.data.number}</button>
  )
}
Child = memo(Child);
function App() {
  let [number,setNumber]=useState(0);
  let [name,setName] = useState('tiya');
  const addClick = useCallback(()=>setNumber(x=>x+1),[]);
  //const addClick = useCallback(()=>setNumber(number+1),[number]);
  const data = useMemo(()=>({number}),[number]);
  
  return (
    <div>
      <input type="text" value={name} onChange={e=>setName(e.target.value)}/>
      <Child addClick={addClick} data={data}/>
    </div>
  );
}
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章