hook的介绍
hook是React 16.8中的一个新添加项。它们允许您在不编写类的情况下使用状态和其他反应特性。
一个简单的例子来对比hook与常规的class的的写法
hook
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
class
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() : this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
那就有个疑问 为什么要用它? 用它会带来哪些好处呢? 它能解决class的哪些问题 ?带着这几个问题我们来想象解读一下hook 看?
运用class带来的问题
1. 组件内逻辑复杂
有状态的组件,当业务复杂时组件间的共享状态变得频繁和复杂,使之难 以维护
所以 我们引用redux来管理状态,但同时也会引发其他问题,如 数据不
一致等
2.性能问题
class的方式需要编译大量冗余代码,而且压缩效果不是很好(这个没有具体实际操练对比过)
3. react的嵌套地狱
运用hook时
1.代码简洁
2.可以让我们在函数式组件中添加state,也可以让我们使用部分生命周期钩子函数 同时简化周期函数,避免重复代码
3.useEffect可以让我们在函数式组件中使用一个副作用( 事件的订阅、dom操作 )不需清除的副作用
比较迷茫吧 来看代码
class
componentDidmount(){
xx.addEventListener()
}
componentWillUnmount(){
xx.addEventListener()
}
hook
useEffect(()=>{
xx.addEventListener();
return ()=>xx.addEventListener()
})
这是effect 可选的清除机制。每个 effect 都可以返回一个清除函数。会在组件卸载的时候执行清除操作
废话不多说 直接转移hook的APi吧
.useState
useState是一种使用this.state在类中提供的完全相同功能的新方法。通常,当函数退出时变量“消失”但React保留状态变量。
useState Hook的唯一参数是初始状态。与类不同,状态不必是对象。他可以是任何我们需要的内容,比如数字,字符串等。在我们的示例中,我们只需要一个数字来表示用户点击的次数,因此将0作为变量的初始状态(如果我们想在状态中存储两个不同的值,我们将调用useState两次。)
它返回一对值:当前状态和更新状态的函数。这就是我们编写const [count,setCount] = useState(0)的原因。这与类中的 this.state.count和this.setState类似,只不过现在它们是成对的。
class定义初始值
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
}
hook定义初始值
import { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
// ...
}
我们声明一个名为count的状态变量,并将其设置为0。React将记住重新渲染之间的当前值,并为我们的函数提供最新的值。如果我们想要更新当前count,我们可以调用setCount
读取状态
<p>You clicked {count} times</p>
更新状态
<button onClick={() : setCount(count + 1)}>
Click me
</button>
.useEffect
熟悉 useEffect ≈ (calss周期函数的componentDidMount,componentDidUpdate 和 componentWillUnmount)三个函数的组合。
将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。我们不需要特殊的 API 来读取它 —— 它已经保存函数作用域中。Hook 使用了 JavaScript 的闭包机制,而不用在 JavaScript 已经提供了解决方案的情况下,还引入特定的 React API
是的,默认情况下,它在第一次渲染之后和每次更新之后都会执行
同时 effect 可选的清除机制。每个 effect 都可以返回一个清除函数。会在组件卸载的时候执行清除操作
useEffect(()=>{
xx.addEventListener();
return ()=>xx.addEventListener()
})
useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
返回一个 memoized 回调函数。
把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。