useReducer
useReducer-基础用法
useReducer-分派action时传参
小结
// useReducer
import { useReducer } from "react"
// 1. 定义reducer函数 根据不同的action 返回不同的状态
function reducer (state, action) {
switch (action.type) {
case 'INC':
return state + 1
case 'DEC':
return state - 1
case 'SET':
return action.payload
default:
return state
}
}
// 2. 组件中调用useReducer(reducer, 0) => [state, dispatch]
// 3. 调用dispatch({type:'INC'}) => 通知reducer产生一个新的状态 使用这个新状态更新UI
function App () {
const [state, dispatch] = useReducer(reducer, 0)
return (
<div className="App">
this is app
<button onClick={() => dispatch({ type: 'DEC' })}>-</button>
{state}
<button onClick={() => dispatch({ type: 'INC' })}>+</button>
<button onClick={() => dispatch({ type: 'SET', payload: 100 })}>update</button>
</div>
)
}
export default App
useMemo
useMemo - 基础语法
// useMemo
// 缓存: 消耗非常大的计算
import { useMemo, useState } from "react"
// 计算斐波那契数列之和
function fib (n) {
console.log('计算函数执行了')
if (n < 3)
return 1
return fib(n - 2) + fib(n - 1)
}
function App () {
const [count1, setCount1] = useState(0)
const result = useMemo(() => {
// 返回计算得到的结果
return fib(count1)
}, [count1])
// const result = fib(count1)
const [count2, setCount2] = useState(0)
console.log('组件重新渲染了')
return (
<div className="App">
this is app
<button onClick={() => setCount1(count1 + 1)}>change count1: {count1}</button>
<button onClick={() => setCount2(count2 + 1)}>change count2: {count2}</button>
{result}
</div>
)
}
export default App
React.memo
React.memo - 基础语法
// React.memo
import { memo, useState } from "react"
// 1. 验证默认的渲染机制 子跟着父一起渲染
// 2. memo进行缓存 只有props发生变化的时候才会重新渲染 (不考虑context)
const MemoSon = memo(function Son () {
console.log('我是子组件,我重新渲染了')
return <div>this is son</div>
})
// function Son () {
// console.log('我是子组件,我重新渲染了')
// return <div>this is son</div>
// }
function App () {
const [count, setCount] = useState(0)
return (
<div className="App">
<button onClick={() => setCount(count + 1)}>+{count}</button>
{/* <Son /> */}
<MemoSon />
</div>
)
}
export default App
React.memo - props的比较机制
useCallback - 基础语法
// useCallback
import { memo, useCallback, useState } from "react"
const Input = memo(function Input ({ onChange }) {
console.log('子组件重新渲染了')
return <input type="text" onChange={(e) => onChange(e.target.value)} />
})
function App () {
// 传给子组件的函数
const changeHandler = useCallback((value) => console.log(value), [])
// 触发父组件重新渲染的函数
const [count, setCount] = useState(0)
return (
<div className="App">
{/* 把函数作为prop传给子组件 */}
<Input onChange={changeHandler} />
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
)
}
export default App
// React.memo props比较机制
// 1. 传递一个简单类型的prop prop变化时组件重新渲染
// 2. 传递一个引用类型的prop 比较的是新值和旧值的引用是否相等 当父组件的函数重新执行时,实际上形成的是新的数组引用
// 3. 保证引用稳定 -> useMemo 组件渲染的过程中缓存一个值
import { memo, useMemo, useState } from 'react'
const MemoSon = memo(function Son ({ list }) {
console.log('子组件重新渲染了')
return <div>this is Son {list}</div>
})
function App () {
const [count, setCount] = useState(0)
// const num = 100
const list = useMemo(() => {
return [1, 2, 3]
}, [])
return (
<div className="App">
<MemoSon list={list} />
<button onClick={() => setCount(count + 1)}>change Count</button>
</div>
)
}
export default App
React.forwardRef
使用ref暴露DOM节点给父组件
forwardRef - 语法实现
import { forwardRef, useRef } from "react"
// 子组件
// function Son () {
// return <input type="text" />
// }
const Son = forwardRef((props, ref) => {
return <input type="text" ref={ref} />
})
// 父组件
function App () {
const sonRef = useRef(null)
const showRef = () => {
console.log(sonRef)
sonRef.current.focus()
}
return (
<>
<Son ref={sonRef} />
<button onClick={showRef}>focus</button>
</>
)
}
export default App
useInperativeHandle
通过ref暴露子组件中的方法
useInperativeHandlle - 场景说明
import { forwardRef, useImperativeHandle, useRef } from "react"
// 子组件
const Son = forwardRef((props, ref) => {
// 实现聚焦逻辑
const inputRef = useRef(null)
const focusHandler = () => {
inputRef.current.focus()
}
// 把聚焦方法暴露出去
useImperativeHandle(ref, () => {
return {
// 暴露的方法
focusHandler
}
})
return <input type="text" ref={inputRef} />
})
// 父组件
function App () {
const sonRef = useRef(null)
const focusHandler = () => {
console.log(sonRef.current)
sonRef.current.focusHandler()
}
return (
<>
<Son ref={sonRef} />
<button onClick={focusHandler}>focus</button>
</>
)
}
export default App