useRef
脱围机制,通过.current
访问
- 数据脱围
- DOM
- 操作组件,19之前需要配合forwardRef包裹子组件,19后就不需要了,并且把第一个参数props合并到了参数ref
useImperativeHandler
对父组件传过来的ref进行属性和操作的可控暴露,感觉有点像defineExpose的功能
tsx
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
// 使用forwardRef转发ref到子组件
const FancyInput = forwardRef((props, ref) => {
// 创建组件内部的ref
const inputRef = useRef();
// 自定义暴露给父组件的ref方法
useImperativeHandle(ref, () => ({
// 只暴露focus方法给父组件
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} />;
});
function App() {
// 创建引用FancyInput组件的ref
const inputRef = useRef();
return (
<div>
<FancyInput ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
Focus the input
</button>
</div>
);
}
export default App;
useContext
相比直接全局变量来说,可以控制注入范围
创建:
tsx
const myContext = React.createContext({}: type)
在注入范围上使用,19后可以不需要加.Provider
tsx
<MyContext.Provider value={{/*type型的值*/}}>
</MyContext.Provider>
注意,如果value传入的对象更改,那么对应的所有引用context的组件也会重新渲染。
可以想到,如果你传入了一个局部函数,或者局部对象,那么每次挂载含有Provider的组件时,也会使得含Context的组件重渲染,所以在重要的地方可以缓存
tsx
function Parent(){
const callback = useCallback(()=>{},[])
const value = useMemo(()=>{
return {fn: callback}
}, [callback])
return <MyContext.Provider value={value}>
<Children />
</MyContext.Provider>
}
子组件使用
tsx
const context = useContext(myContext)