React Hooks 初识
Hooks是React16 推出的一个功能:让函数组件具有类组件的能力。 Hooks 极大改变了 React 应用开发的模式和开发体验。
随着 hooks的使用,将来越来越多的组件将使用函数组件,而不再是class组件。Hooks代表着未来react开发的新趋势。
计数器demo
通过计数器的 demo 来学习hooks。
场景:
假设现在需要一个计数器组件,有一个本地的状态count,每隔1s,count增加1。
如果不使用hooks,按照之前的写法是:
import React from 'react';
class Counter extends React.Component {
constructor() {
super();
this.state = {
count: 10
};
}
// 组件挂载后,设置定时器
componentDidMount() {
// 注意,定时器中的setState是同步的
this.interval = setInterval(()=>{
this.setState({count: this.state.count + 1})
}, 1000)
}
// 在组件中使用了定时器,一定记得在组件卸载时,要清除定时器
// 如果忘记清除了,那么在组件卸载后,这个定时器依旧存在,不仅消耗内存引起内存泄露,而且定时器还会调用setState的方法,但此时setState已经不存在了,所以会报错
componentWillUnmount() {
if(this.interval) {
clearInterval(this.interval);
}
}
render() {
return <h3>{ this.state.count }</h3>
}
}
或者,使用类属性新特性来声明状态:
import React from 'react';
class Counter extends React.Component {
state = {
count: 10
}
render() {
return (
<div>
<h3>{ this.state.count }</h3>
<button onClick={}>加1</button>
</div>
)
}
}
以上的功能,在以前是无法在function组件中实现的,因为function组件没有state,没有生命周期。
可是现在有了hooks,一切就不同了。
import React, { useState, useEffect } from 'react';
function Counter() {
// useState声明一个state:count, 和更新state的方法:setCount
// count的默认state是0
const [count, setCount] = useState(0);
// 组件挂载后,执行回调
useEffect(() => {
const interval = setInterval(() => {
// c对应最新的state
setCount(c => c + 1)
}, 1000)
// 组件卸载时,执行return的函数
return () => clearInterval(interval)
}, [])
return <span>{count}</span>
}
export default Counter;
使用useState和useEffect,可以给function组件增加类似state和生命周期方法的效果。
使用useState声明状态,返回状态和更新状态的方法。
useEffect 方法,可以在组件更新完成之后,执行传入的回调,组件卸载时执行return的函数来做一些清理的工作。class组件有生命周期函数,function组件是没有生命周期函数的。可以使用useEffect 来模拟类组件的生命周期。
State Hokks有两个API:useState和useReducer。
useState其实是基于useReducer实现的一个API,useReducer才是react中基础的,关于状态管理的hook。
正如我们的经验,越底层的东西,使用越不简单,也越不常用。越上层的封装,使用越简单,也更常用。
所以,相比较useReducer,useState的使用频率更高,使用起来也更简单。
useState
通过useState传入默认值之后,返回一个数组,里面有两个变量(可以通过const res = useCount(0), 打印res来看看数组长什么样),一般都是通过数组解构,数组第一项作为一个state,第二项是更新该state的方法。比如,
const [count, setCount] = useState(0);
注意点:
1.传入的默认值
2.setCount有两种用法:
setCount(1): 传入一个值:传入什么,state的值就变成什么。
setCount(c => c+1): 传入一个回调,回调函数的参数是当前最新的state,可以针对当前最新的state做些事情。
两种方式最大的区别是:
使用第一种方式,是直接覆盖的用法,参数中的state可能并不是最新的state,造成得不到我们想要的结果的情况。可能导致闭包陷阱。
使用第二种方式,回调函数的参数拿到是当前最新的state。可以规避闭包陷阱。
useReducer
useState其实是基于useReducer实现的hook,只不过会变得更加常用,使用方式更简单。
useReducer才是真正的基础的react 中关于状态管理的hook。
useReducer的用法很类似redux:
import React, { useReducer } from 'react';
// 定义Reducer函数,就像redux中定义reducer函数那样
// 接收一个state和action作为参数
function counterReducer(state, action) {
switch(action.type) {
case 'add':
return state + 1;
case 'minus':
return state - 1;
default:
return state;
}
}
// 使用
function Counter() {
// useReducer接收两个参数,第一个参数是reducer函数,第二个参数是初始的state
// 返回一个数组,第一个参数是初始的state, 第二个参数是用来专门派发action的方法,只对当前的state生效
const [ count, dispatchCounter ] = useReducer(counterReducer, 0);
useEffect(() => {
const interval = setInterval(() => {
// dispatchCounter接收一个action作为参数
dispatchCounter({type: 'add'})
}, 1000)
return () => clearInterval(interval)
}, [])
return (
<span>{ count }</span>
)
}
最后
React Hooks 改变了类组件的繁重的开发方式,提供了一种更简洁,轻便,灵活的开发体验,也是现今 React 的主流开发方式。
转载自:https://juejin.cn/post/7205181884590194749