关于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>)}
