这是我参与更文挑战的第23天,活动详情查看: 更文挑战
1, useImperativeHandle
1 ,用法
useImperativeHandle(ref, createHandle, [deps])
useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用:
useImperativeHandle(ref(传递来的), ()=>{}, [])
2, 举例
import './App.css';
import React , { useRef, forwardRef , useImperativeHandle, useState } from 'react'
const ForWard = forwardRef((props, ref) => {
return (
<>
<h2 ref={ref}>12345</h2>
<h2>JamieDawn</h2>
</>
)
})
const Imperative = forwardRef((props, ref) => {
const inputRef = useRef(null)
const [count, setCount] = useState(0)
const [num, setNum] = useState(0)
useImperativeHandle(ref, ()=> {
console.log('useImperativeHandle')
return ({
name: 'zlm',
focus: ()=> {
inputRef.current.focus()
}
})
}, [num])
return (
<>
<h2>count{count}</h2>
<h2>num{num}</h2>
<input type="text" ref={inputRef} />
<button onClick={()=>{setCount(count + 1)}}>setCount</button>
<button onClick={()=>{setNum(num + 1)}}>setNum</button>
</>
)
})
function App() {
const hRef = useRef(null)
const el = useRef(null)
return (
<>
<ForWard ref={hRef}/>
<Imperative ref={el} />
<button onClick={()=> {
console.log(hRef.current)
}}>获取forWardRef</button>
<button onClick={()=> {
console.log(el.current)
el.current.focus()
}}>获取Imperative</button>
</>
);
}
export default App;
2, useLayoutEffect
1, 用法
其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
尽可能使用标准的 useEffect 以避免阻塞视觉更新。
注意: useLayoutEffect 和 useEffect 不同之处: 执行的时间不同,useEffect是在componentDidMount以后执行的,useLayoutEffect是在浏览器执行绘制之前执行,会阻塞组件挂载,慎用
2, 举例
import './App.css';
import React , { useEffect, useLayoutEffect } from 'react'
function App() {
useEffect(() => {
console.log('useEffect')
return ()=> {
console.log('useEffect-return')
}
})
useLayoutEffect(() => {
console.log('useLayoutEffect')
return () => {
return () => {
console.log('useLayoutEffect-return')
}
}
})
return (
<>
<h2>useLayoutEffect</h2>
</>
);
}
export default App;
3, 执行
首先: useLayoutEffect 执行
然后: useEffect 执行
组件在消毁或者改变状态的时候
首先: useLayoutEffect-return 执行
然后: useLayoutEffect 执行
接着: useEffect-return 执行
最后: useEffect 执行
3, useReducer
1, 用法
const [state, dispatch] = useReducer(reducer, initialArg, init);
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)
在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优
化,因为你可以向子组件传递 dispatch 而不是回调函数 。
2,说明
1, useReducer 和 redux中的Reducer是一样的,说白了Reducer就是一个函数
2, useReducer()是一个函数,有三个参数, 第一个参数:reducer, 第二个参数:初始值, 第三个参数:init
3, useReducer()返回值是一个数组,第一个是state, 第二个是dispatch
4, const [state, dispatch] = useReducer(reducer, 初始值)
3, 举例
import './App.css';
import React , { useReducer } from 'react'
function App() {
const [state, dispatch] = useReducer((state, action)=> {
switch(action.type) {
case 'setname':
return {...state, name: action.name}
case 'setage':
return {...state, age: action.age}
default:
return state
}
}, {name: 'zlm', age: 19})
return (
<>
<h2>姓名:{state.name}, age: {state.age}</h2>
<button onClick={ ()=> {
dispatch({
type: 'setname',
name: 'Jamied'
})
}}>setName</button>
<button onClick={()=> {
dispatch({
type: 'setage',
age: '30'
})
}}>setAge</button>
</>
);
}
export default App;
注意:
useReducer, useContext, createContext = redux
可以实现redux功能