关于useEffect https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/
关于useContext的优化 http://www.ptbird.cn/react-createContex-useContext.html
React.forwardRef
React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中(作为回调的第二个参数。这种技术并不常见,但在以下两种场景中特别有用:
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
ps:
Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说,这通常不是必需的。但其对某些组件,尤其是可重用的组件库是很有用的。
//是指把组件真实dom的引用传递到外部。这个引用通过React.createRef();创建
https://zh-hans.reactjs.org/docs/forwarding-refs.html
useState
一个闭包+异步问题
a是一个基础类型,如果useEffect不传第二个参数且组件没有重新渲染,a永远是初始值1
此时应该用setState(a1=>a1+1),a1是setState内部维护的最新值。
import React, { useState,useEffect} from 'react';
function Component() {
const [a, setA] = useState(0);//定义变量a,并且默认值为0
//定义第1个useEffect,专门用来处理自动累加器
useEffect(() => {
let timer = setInterval(() => {setA(a+1)},1000);// <-- 请注意这行代码,暗藏玄机
return () => {
clearInterval(timer);
}
}, []);//此处第2个参数为[],告知React以后该组件任何更新引发的重新渲染都与此useEffect无关
//定义第2个useEffect,专门用来处理网页标题更新
useEffect(() => {
document.title = `${a} - ${Math.floor(Math.random()*100)}`;
},[a])
return <div> {a} </div>
}
export default Component;
useEffect
指定useEffect第二个参数,明确监听的值,减少性能损耗。(不带参数默认是监听所有update
import React, { useState,useEffect} from 'react';
function Component() {
const [obj,setObj] = useState({a:0,b:0});
useEffect(() => {
document.title = `${obj.a} - ${Math.floor(Math.random()*50)}`;
}); //注意此时我们并未设置useEffect函数的第2个参数
return <div>
{JSON.stringify(obj)}
<button onClick={() => {setObj({...obj,a:obj.a+1})}}>a+1</button>
<button onClick={() => {setObj({...obj,b:obj.b+1})}}>a+1</button>
</div>
}
export default Component;
usememo
useCallback
由于function是引用类型,每次渲染反复创建新function,会导致依赖于function的子组件无法优化的阻止更新
usecallback
useCallback
当方法依赖的deps改变时才新建方法
import React from 'react'
function Button({label,clickHandler}) {
//为了方便我们查看该子组件是否被重新渲染,这里增加一行console.log代码
console.log(`rendering ... ${label}`);
return <button onClick={clickHandler}>{label}</button>;
}
export default React.memo(Button); //只能对props进行浅比较
----------------------
function Mybutton() {
const [age,setAge] = useState(34);
const [salary,setSalary] = useState(7000);
useEffect(() => {
document.title = `Hooks - ${Math.floor(Math.random()*100)}`;
});
//按钮执行一次之后,该组件重新渲染,然后function是重新生成的,指向不同的引用
//绑定作为子组件的props时会看作不同的值,导致绑定方法的子组件都重新渲染
const clickHandler01 = () => {
setAge(age+1);
};
const clickHandler02 = () => {
setSalary(salary+1);
};
//useCallback会在react内维护上一次创建的方法的内存,如果重新赋值
const clickHandler01 = useCallback(() => {
setAge(age+1);
},[age]);
return (
<div>
{age} - {salary}
<Button label='Bt01' clickHandler={clickHandler01}></Button>
<Button label='Bt02' clickHandler={clickHandler02}></Button>
</div>
)
}