跳到主要内容

useRef 和 useContext 等其他 Hooks

其他 Hooks

  • useRef
  • useContext
  • useReducer
  • useMemo
  • useCallback

useRef 使用

例子

import React, {useEffect, useRef} from "react";

function UseRefDemo() {
const btnRef = useRef(null) // 初始值
const numRef = useRef(100);
console.log(numRef.current) // 100

useEffect(() => {
console.log(btnRef.current) // DOM 节点 <button>click</button>
}, [])

return <div>
<button ref={btnRef}>click</button>
</div>
}

export default UseRefDemo

useContext 使用

例子

import React, {useContext} from "react";

const themes = {
light: {
foreground: '#000',
background: '#eee'
},
dark: {
foreground: '#fff',
background: '#222'
}
}
// 创建 Context
const ThemeContext = React.createContext(themes.light)

// 孙子组件
function ThemeButton() {
const theme = useContext(ThemeContext);
return <button style={{background: theme.background, color: theme.foreground}}>
hello world
</button>
}

// 子组件
function Toolbar() {
return <div>
<ThemeButton></ThemeButton>
</div>
}

// 父组件
function UseContextDemo() {
return <ThemeContext.Provider value={themes.dark}>
<Toolbar></Toolbar>
</ThemeContext.Provider>
}

export default UseContextDemo

useReducer 的使用

useReducer 能代替 redux 吗

  • useReducer 是 useState 的替代方案,用于 state 复杂变化
  • useReducer 是单个组件状态管理,组件通讯还需要 props
  • redux 是全局的状态管理,多组件共享数据

例子

import React, {useReducer} from "react";

const initialState = {count: 0}
const reducer = (state, action) => {
switch (action.type) {
case 'increment' :
return {count: state.count + 1}
case 'decrement':
return {count: state.count - 1}
default:
return state
}
}

function UseReducerDemo() {
// 很像 const [count,setCount] = useState(0)
const [state, dispatch] = useReducer(reducer, initialState)

return <div>
count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>increment</button>
<button onClick={() => dispatch({type: 'decrement'})}>decrement</button>
</div>
}

export default UseReducerDemo

useMemo 使用

使用 useMemo 做性能优化

  • React 默认会更新所有子组件
  • class 组件使用 SCU 和 PureComponect 做优化
  • Hooks 中使用 useMemo,但优化的原理是相同的

例子

import React, {memo, useMemo, useState} from "react";

// 子组件
// function Child({userInfo}) {
// console.log('child render ...', userInfo)
//
// return <div>
// <p>this is child {userInfo.name} {userInfo.age}</p>
// </div>
// }

// 类似 class PureComponent,对 props 进行浅层比较
const Child = memo(({userInfo}) => {
console.log('child render ...', userInfo)

return <div>
<p>this is child {userInfo.name} {userInfo.age}</p>
</div>
})

// 父组件
function UseMemoDemo() {
console.log('parent render ...')

const [count, setCount] = useState(0)
const [name, setName] = useState('lzw')

// const userInfo = {name, age: 20}
// 用 useMemo 缓存数据,有依赖
const userInfo = useMemo(() => {
return {name, age: 21}
}, [name])

return <div>
<p>
count is {count}
<button onClick={() => setCount(count + 1)}>click</button>
</p>
<Child userInfo={userInfo}></Child>
</div>
}

export default UseMemoDemo

useCallback 使用

使用 useCallback 做性能优化

  • useMemo 缓存数据
  • useCallback 缓存函数
  • 两者是 React Hooks 的常见优化策略

例子

import React, {memo, useMemo, useState, useCallback} from "react";

// 子组件, memo 类似 class PureComponent,对 props 进行浅层比较
const Child = memo(({userInfo, onChange}) => {
console.log('child render ...', userInfo)

return <div>
<p>this is child {userInfo.name} {userInfo.age}</p>
<input onChange={onChange}/>
</div>
})

// 父组件
function UseCallbackDemo() {
console.log('parent render ...')

const [count, setCount] = useState(0)
const [name, setName] = useState('lzw')

// 用 useMemo 缓存数据,有依赖
const userInfo = useMemo(() => {
return {name, age: 21}
}, [name])

// function onChange(e) {
// console.log(e.target.value)
// }
// 用 useCallback 缓存函数
const onChange = useCallback(e => {
console.log(e.target.value)
}, []);


return <div>
<p>
count is {count}
<button onClick={() => setCount(count + 1)}>click</button>
</p>
<Child userInfo={userInfo} onChange={onChange}></Child>
</div>
}

export default UseCallbackDemo