注意:hooks只能在函数(无状态组件)中使用
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。(官方介绍)
forwardRef:
引用父组件的ref实例,成为子组件的一个参数,可以引用父组件的ref绑定到子组件自身的节点上.useImperativeHandle : 第一个参数,接收一个通过forwardRef引用父组件的ref实例,第二个参数一个回调函数,返回一个对象,对象里面存储需要暴露给父组件的属性或方法
//Test.tsx文件
import React, {
FC, Fragment, useRef, MutableRefObject, forwardRef, ForwardRefExoticComponent, Ref, useImperativeHandle, ChangeEvent, SyntheticEvent, memo } from "react";
const Test: FC = (): JSX.Element => {
const testRef: MutableRefObject<any> = useRef('test');
const handleClick = (e:SyntheticEvent<HTMLButtonElement>):void =>{
console.log('自身button的内容:',e.currentTarget.innerText);
console.log('子组件input的对象:',testRef.current);
console.log('子组件input的value值:',testRef.current.value);
console.log('子组件input的类型:',testRef.current.type());
}
return (
<Fragment>
<TestChildForward ref={
testRef} />
<button onClick={
handleClick}>获取子组件的input的value和type</button>
</Fragment>
);
}
export default Test;
function TestChild(props:{
},ref: Ref<any>): JSX.Element {
const testRef: MutableRefObject<any> = useRef();//创建一个自身的ref,绑定到标签节点上
//暴露出一个想要让父组件知道的对象,里面可以是属性也可以是函数
useImperativeHandle(ref,()=>{
//第一个参数,要暴露给哪个(ref)?第二个参数要暴露出什么?
return {
//(testRef.current as HTMLInputElement) 类型断言,自己肯定就是这样的类型
value:(testRef.current as HTMLInputElement).value,//暴露出input的value
type:()=>(testRef.current as HTMLInputElement).type//暴露出input的type类型
}
});
return (
<>
<input type="text" value={
'input的内容'} ref={
testRef} onChange={
(e:ChangeEvent<HTMLInputElement>)=>{
console.log(e.currentTarget.value);
console.log(e.currentTarget.type);
}}/>
</>
);
}
const TestChildForward:ForwardRefExoticComponent<any> = memo(forwardRef(TestChild));
从上面的结果可以看到,当我们不想向父组件暴露太多的东西的时候,可以使用useImperativeHandle来按需暴露给父组件一些东西
其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。尽可能使用标准的 useEffect 以避免阻塞视觉更新。
import React, {
useDebugValue, useState } from 'react';
const useTest = () => {
const [str, setStr] = useState<string>('');
useDebugValue('debug');
return {
str, setStr
}
}
export default (): JSX.Element => {
const {
str, setStr } = useTest();
return (
<>
<h2>{
str}</h2>
<button onClick={
() => {
setStr('重新渲染');
}}>这是???</button>
</>
);
}
会在自定义的hooks标记到react的调试工具上面,主要用于调试工具调试使用
import React, {
useDebugValue, useState } from 'react';
const useTest = () => {
const [str, setStr] = useState<string>('');
useDebugValue(str, (value:string) => {
console.log(value);
return '这是改造后的' + value;
});
return {
str, setStr
}
}
export default (): JSX.Element => {
const {
str, setStr } = useTest();
return (
<>
<h2>{
str}</h2>
<button onClick={
() => {
setStr('重新渲染');
}}>这是???</button>
</>
);
}
由于str的初始值是空的,所以打印就是空的了,这只是调试使用,hooks差不多就这些了,没有其他的了
下面会写一些管理react和vue的一些TypeScript类型的总结
React进阶用法和hooks的个人使用见解:
1.lazy+Suspense懒加载的使用
2.hooks的useState、useEffect、自定义钩子的实际使用
3.useCallback+useMemo+memo性能优化
4.useReducer+useContext+createContext的使用、模拟redux合并reducer