react最罕用的hooks有,useState,useEffect,useMemo,useCallback
首先咱们来先聊useState,设置和扭转state,代替原来的state和setState
import { useState } from "react";import './index.css'export default () => { const [ count, setCount ] = useState(0); const handleClick = ()=>{ console.log(count)//0 setCount(count + 1); } return ( <div className='container'> <h3> 计算结果: {count} </h3> <button onClick={()=>handleClick()}>每次加一</button> </div> );};setState的‘异步’并不是说外部由异步代码实现,其实自身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用程序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,造成了所谓的‘异步’(有一个变量isBatchingUpdates和batchedUpdates来解决这个问题)
useEffect 代替原来的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版
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;useMemo 是做什么的,一言以蔽之,做性能优化用的,如果说类组件的性能优化的办法是 shouldComponentUpdate 和 PureComponent,那么给函数组件做性能优化的就是这个 useMemo。
//parant.jsximport React, { useState } from 'react';import Son from '../component/Son'export default (props)=>{ const [number,setNumber]=useState(0) const [name, setName]=useState('Yui') return( <div className='flex flex-col'> <button className='pb-10' onClick={()=>{setNumber(number+1)}}>{'number is:'+number}</button> <button onClick={()=>{setName('rena')}}>{'change name'}</button> <Son name={name}/> </div> )}//child.jsximport React, { Component, useMemo } from "react";export default (props) => { const Data= useMemo(() =>{ console.log('render') return props.name+'wowode' }, [props.name]) return ( <> <div>{Data}</div> </> );};useCallback 把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项扭转时才会更新。当你把回调函数传递给通过优化的并应用援用相等性去防止非必要渲染(例如 shouldComponentUpdate)的子组件时,它将十分有用
import React, {useState, memo, useCallback} from 'react';function Home(props) { console.log('Home被渲染了'); return ( <div> <p>Home</p> <button onClick={()=>{props.handler()}}>减少</button> </div> )}function About(props) { console.log('About被渲染了'); return ( <div> <p>About</p> <button onClick={()=>{props.handler()}}>缩小</button> </div> )}const MemoHome = memo(Home);const MemoAbout = memo(About);function App() { console.log('App被渲染了'); const [numState, setNumState] = useState(0); const [countState, setCountState] = useState(0); function increment() { setNumState(numState + 1); } // 以下代码的作用: 只有countState没有发生变化, 那么useCallback返回的永远都是同一个函数 const decrement = useCallback(()=>{ setCountState(countState - 1); }, [countState]); return ( <div> <p>numState = {numState}</p> <p>countState = {countState}</p> <MemoHome handler={increment}/> <MemoAbout handler={decrement}/> </div> )}export default App;