本帖最后由 懒,羊羊 于 2019-5-9 22:53 编辑
#### Hooks 简介
> React 16.8新特性。它可以让你在不编写class的情况下使用state以及其他react特性
#### 使用useState Hook实现计数器
[JavaScript] 纯文本查看 复制代码 import React, { useState, Fragment } from 'react'
import ReactDOM from 'react-dom'
function NumCount() {
const [ count, setCount ] = useState(0)
const Click = () => {
setCount(count + 1)
}
return (
<Fragment>
<p>You clicked {count} times</p>
<button onClick={Click}>Clicl Me</button>
</Fragment>
)
}
ReactDOM.render(<NumCount />, document.getElementById('root'))
> 在这里,useState 就是一个Hook.通过在函数组件中调用它用来给组件添加一些内部的state。useState会返回一队值,当前状态和让你更新它的函数,你可以在事件处理函数中或者其他一些地方调用这个函数。它类似于class中this.setState,但是它不会吧新的state和旧的state进行合并
#### 等价的class组件示例(计数器)
[JavaScript] 纯文本查看 复制代码 import React, { Fragment } from 'react'
import ReactDOM from 'react-dom'
class NumCount extends React.Component {
state = {
count: 0
}
render() {
return (
<Fragment>
<p>You clicked {this.state.count} times</p>
<button onClick={this.Click.bind(this)}>Click Me</button>
</Fragment>
)
}
Click() {
this.setState({
count: this.state.count + 1
})
}
}
ReactDOM.render(<NumCount />, document.getElementById('root'))
#### 那么什么是Hook?
**Hook是一些可以让你在函数组件中'勾入'React State 及生命周期等特性的函数**
**React内置了一些像useState这样的Hook,当然也可以通过创建自己的Hook来复用不同组件之间的状态逻辑。**
**Hook 允许我们通过代码的用途分离它们**
#### useEffect hook 实现计数器将count显示在document.title上
[JavaScript] 纯文本查看 复制代码 function Count() {
const [ count, setCount ] = useState(0)
const clickHandle = () => {
setCount(count + 1)
}
useEffect(
() => {
let timer = setInterval(() => {
setCount(count + 1)
}, 1000)
return () => {
clearInterval(timer)
}
},
[ count ]
)
return (
<Fragment>
<p>You clicked {count} times</p>
<button onClick={clickHandle}>Click Me</button>
</Fragment>
)
}
> useEffect可以看作componentDidMount,componentDidUpdate,componentWillUnmount三个钩子函数的组合,**解决了class生命周期函数经常包含不相关的逻辑,但是又把相关逻辑分离到几个不同的方法中去。**
#### 等价的class组件实现
[JavaScript] 纯文本查看 复制代码 class Count extends React.Component {
state = {
count: 0
}
render() {
return (
<Fragment>
<p>You clicked {this.state.count} times</p>
<button onClick={this.clickHandle.bind(this)}>Click Me</button>
</Fragment>
)
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`
}
clickHandle() {
this.setState({
count: this.state.count + 1
})
}
}
> 比较发现class组件中需要在两个生命周期函数中写重复的代码。
##### 出现动机
**解决了编写和维护组件时遇到的各种各样不相关的问题**
1.在组件之间复用状态逻辑很难
- React没有提供将一些可复用的行为“附加”到组件的途径(如:把组件连接到store),虽然我们可以通过**render props**和**高阶组件**来解决此类问题,但是会很麻烦使自己的代码难以理解。
1. 说明了一个问题: **React需要为共享状态逻辑提供更好的原生途径**
2. 使用Hooks可以从组件中提取状态逻辑,使得这些逻辑可以单独测试并且复用。**Hooks可以使你在无需修改组件结构的情况下复用状态逻辑。**
2.复杂组件变得难以理解
- 每个生命周期常常包含一些不相关的逻辑。例如:组件常常在**componentDidMount**和**componentDidUpdate**中获取数据,但是同一个**componentDidMount**中可能包含很多其他逻辑,如设置事件监听,而之后需要在**componentWillUnmount**中清除。相互关联且需要且需要对照修改的代码被进行了拆分,而完全不相关的的代码却在同一个方法中组合在一起。这样很容易产生bug而且导致逻辑不一致。
1. 为了解决这个问题,Hooks将组件中相互关联的部分拆分成更小的函数,而并非强制按照声明周期划分
3.难以理解的class(没有计划从react中移除class)
- 学习react,class是一大屏障,你必须去理解JavaScript中this的工作方式.class也给一些工具带来问题,class不能很好的压缩,会使热重载出现不稳定的情况
1. 为了解决这些问题,Hooks让使你在非class的情况下可以使用更多的React特性。react组件一直更像是函数,而Hooks则拥抱了函数,同时也没有牺牲react的精神原则,hooks提供了问题的解决方案,无需学习复杂的函数式或响应式编程。
**Hook和现有的代码可以同时工作,你可以渐进使用Hooks,不用着急迁移**
#### Hook规则
> Hook本质就是JavaScript函数,使用它时要遵循两条规则。linter插件来强制执行这些规则
##### 只在最顶层使用Hook
**确保总是在你的React函数的最顶层点用它们,遵循这条规则能确保Hook在每一次渲染中都按照同样的顺序被调用。这让React能够在多次useState,useEffect调用之间保持Hook状态的正确**
##### 只在React函数中调用Hook
##### 单个组件多次使用State hook 和Effect Hook,React怎么知道那个state对应那个useState?
> 答案是react靠的是Hook的调用顺序,只要Hook的调用顺序在多次渲染之间保持一致,React就能正确的将内部state和对应的Hook进行关联
|