useState
用來聲明狀態變量。html
import React, { useState } from 'react'; // ... const [ count , setCount ] = useState(0); // ...
- count 聲明的變量
- setCount 設用來更新變量的函數
- 0 初始值
- 多個狀態聲明不能出如今條件判斷語句中
useEffect
用來代替生命週期函數。react
import React, { useEffect } from 'react'; useEffect(()=>{ // some code })
- 第一次組件渲染和每次組件更新都會執行這個函數
- useEffect中的函數的執行不會阻礙瀏覽器更新視圖,這些函數是異步的
使用 useEffect 實現相似 componentWillUnmountredux
useEffect(()=>{ return () => { // some code } })
- 返回一個函數實現解綁
- 可是這樣會致使每次狀態發生變化,useEffect 都進行解綁
useEffect(()=>{ return () => { // some code } }, [])
使用第二個參數,制定哪些狀態發生變化時再解綁瀏覽器
useContext
跨越組件層級直接傳遞變量,實現狀態共享。緩存
- useContext 解決的是組件之間值傳遞的問題
- redux 解決的是應用中統一管理狀態的問題
- useContext 經過和 useReducer 的配合使用,能夠實現相似 Redux 的做用
Outer 組件異步
import React, { createContext } from 'react' const ValueContext = createContext() function Outer(){ return ( <> <ValueContext.Provider value={'我是傳向 Inner 組件的值'}> <Inner /> </ValueContext.Provider> </> ) } export default Outer;
- 使用 createContext 建立 context
- 使用 createContext 同時生成組件
- 閉合標籤將組件包裹
Inner 組件ide
import React, { useContext } from 'react' const value = useContext(CountContext) function Inner(){ return ( <> <p>{value}</p> </> ) } export default Inner;
使用 useContext 來使用上下文函數
useReducer
用來實現相似 redux 功能性能
import React, { useReducer } from 'react'; function Demo(){ const [ count, dispatch ] = useReducer((state,action)=>{ switch(action){ case 'add': return state+1 case 'sub': return state-1 default: return state } },0) return ( <> <h2>分數:{count}</h2> <button onClick={()=>dispatch('add')}>加</button> <button onClick={()=>dispatch('sub')}>減</button> </> ) } export default Demo
- state 第一個參數 狀態
- action 控制業務邏輯的判斷參數
模擬 Redux
- useContext:可訪問全局狀態,避免一層層的傳遞狀態
- useReducer:經過action的傳遞,更新複雜邏輯的狀態
顏色共享組件 color.js字體
import React, { createContext,useReducer } from 'react'; export const ColorContext = createContext({}) export const UPDATE_COLOR = 'UPDATE_COLOR' const reducer = (state, action) => { switch(action.type){ case UPDATE_COLOR: return action.color default: return state } } export const Color = props => { const [color, dispatch] = useReducer(reducer, 'blue') return ( <ColorContext.Provider value = {{color,dispatch}}> {props.children} </ColorContext.Provider> ) }
- 用 {props.children} 來顯示子組件
- 將 color 和 dispatch 共享出去
showArea.js
import React , { useContext } from 'react'; import { ColorContext } from './color'; function ShowArea(){ const { color } = useContext(ColorContext) return (<div style={{ color:color }}>字體顏色爲{ color }</div>) } export default ShowArea
- 注意 引入 ColorContext 使用了大括號
Buttons.js
import React , { useContext } from 'react'; import { ColorContext, UPDATE_COLOR } from './color' function Buttons(){ const { dispatch } = useContext(ColorContext) return ( <div> <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"red"})}}>紅色</button> <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"yellow"})}}>黃色</button> </div> ) } export default Buttons
Demo.js
import React, { useReducer } from 'react'; import ShowArea from './ShowArea'; import Buttons from './Buttons'; import { Color } from './color'; //引入Color組件 function Demo(){ return ( <> <Color> <ShowArea /> <Buttons /> </Color> </> ) } export default Demo
useMemo
用來解決使用 React hooks 產生的無用渲染的性能問題。
import React , {useState,useMemo} from 'react'; function Demo(){ const [xiaohong , setXiaohong] = useState('小紅待客狀態') const [zhiling , setZhiling] = useState('志玲待客狀態') return ( <> <button onClick={()=>{setXiaohong(new Date().getTime())}}>小紅</button> <button onClick={()=>{setZhiling(new Date().getTime()+',志玲向咱們走來了')}}>志玲</button> <ChildComponent name={xiaohong}>{zhiling}</ChildComponent> </> ) } function ChildComponent({name,children}){ function changeXiaohong(name){ console.log('她來了,她來了。小紅向咱們走來了') return name+',小紅向咱們走來了' } const actionXiaohong = changeXiaohong(name) return ( <> <div>{actionXiaohong}</div> <div>{children}</div> </> ) } export default Demo
點擊志玲按鈕,小紅對應的方法執行,雖然結果沒變,可是每次都執行,損耗性能。
function ChildComponent({name,children}){ function changeXiaohong(name){ console.log('她來了,她來了。小紅向咱們走來了') return name+',小紅向咱們走來了' } const actionXiaohong = useMemo(()=>changeXiaohong(name),[name]) return ( <> <div>{actionXiaohong}</div> <div>{children}</div> </> ) }
第二個參數 [name] 匹配成功,纔會執行。
useRef
- 用來獲取React JSX中的DOM元素
- 用來保存變量
import React, { useRef} from 'react'; function Demo(){ const inputEl = useRef(null) inputEl.current.value = "給 input value屬性 賦值" return ( <> <input ref={inputEl} type="text"/> </> ) } export default Demo
import React, { useRef, useState, useEffect } from 'react' function Demo(){ const inputEl = useRef(null) inputEl.current.value="給 input value屬性 賦值" const [text, setText] = useState('默認值') const textRef = useRef() useEffect(()=>{ textRef.current = text }) return ( <> <input ref={inputEl} type="text"/> <input value={text} onChange={(e)=>{setText(e.target.value)}} /> </> ) } export default Demo
- text 每次發生變化,將值保存到 useRef 中
- 使用 useEffect 實現每次狀態變化都進行變量從新賦值
- 不多用到這個功能(保存變量)
自定義 Hooks
編寫自定義函數實現獲取瀏覽器窗口
import React, { useState, useEffect, useCallback } from 'react'; function useWinSize(){ const [ size , setSize] = useState({ width:document.documentElement.clientWidth, height:document.documentElement.clientHeight }) const onResize = useCallback(()=>{ setSize({ width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }) },[]) useEffect(()=>{ window.addEventListener('resize',onResize) return ()=>{ window.removeEventListener('resize',onResize) } },[]) return size; } function Demo(){ const size = useWinSize() return ( <div>頁面Size:{size.width} x {size.height}</div> ) } export default Demo
- 命名要使用 use 開頭以確認該函數是自定義 Hook 而不是組件
- useCallback 用來緩存方法 ( useMemo 是爲了緩存變量)
- 第一次進入方法時用 useEffect 來註冊 resize 監聽事件
- 防止一直監聽因此在方法移除時,使用return的方式移除監聽
- 最後在 Demo 組件中使用
文章參考
- 官方文檔
- 嗶哩嗶哩up主技術胖的 視頻
原文出處:https://www.cnblogs.com/guangzan/p/12210806.html