出现原因
增强函数功能,理论上可以替代类组件。
类组件的缺点:
繁琐的生命周期;
this指向问题//bind绑定this;箭头函数;
函数组件每一次渲染都重新运行。类组件每次只运行reder函数。
hook特点:命名以use开头。
stateHooks/useState横向切分关注点
调用useState返回状态值和改变状态的函数(引用不变,节约内存空间)。状态值改变(如点击显示隐藏)一定重新渲染(状态值不变不会重新渲染(优化目的)),重新运行函数。
整体一个函数组件useState工作流程:
第N次调用useState:
检查该节点的状态数组是否存在下标N
不存在:使用默认值创建一个状态,将该状态加入到状态数组中,下标为N
存在:忽略默认值,得到状态值
useState不可以出现在判断里,和流程有关。由于在判断里之前的下标会改变,造成下标混乱,状态不对应。
性能优化,如果一个元素经常隐藏和显示使用style属性控制 style={{ display: visable ? "block" : "none" }}。
千万不要直接改变状态。react理念:数据要保持纯净,之前的状态是不可变的。
如何强制刷新:
类组件:this.forceUpdate()
函数组件:使用空对象的useState
const [, forceUpdate] = useState({}); forceUpdate({});
//两个对象的地址不一样。
dom事件中状态改变是异步的,此时不能信任之前的状态,应该使用回调函数setState(prev => prev + 1)。
useRef
createRef地址每次不一样,useRef地址唯一。
useEffect
用作处理副作用,比如计时器,操作dom,ajax请求等。运行时机:此hook在页面渲染完毕后会运行一次,此时ui已呈现到用户面前。
useEffect是异步的。
返回值可以是清理函数也可以返回ubdefined不做处理。
接收两个参数:
第一个参数在一开始会调用一次。运行时机:类比类组件生命周期就是componentDidMount。
第二个参数是一个数组依赖项,如果传入一个空数组,只运行一次。如果传入其他,会使用Object.is进行比较,改变时会重新运行此hook。
useMemo
用法和useEffect相同,区别点在于,不用在每次子组件更新时重复运行,只在依赖变化时运行。
useCallback
和useMemo相同,依赖变化时执行。
数据问题
React.createContext()创建一个上下文
const Data = React.createContext({user: 'meituan'});
<Data.Provider value={}>
<Data.Consumer>
</Data.Consumer>
</Data.Provider>
unstated-next
提供createContainer包装一个自定义hook。提供useContainer使用自定义hook返回的数据。Provider 用于对某个作用域注入数据。