目录
Hooks
Hooks优势
- 方便复用状态逻辑
- 副作用的专注点分离
- 函数组件无this问题
使用函数组件也有以下几点好处:
- 风格清爽,函数式编程风格,函数式组件、状态保存在运行环境、每个功能都包裹在函数中,整体风格更清爽,更优雅。
- 代码量小
- 可以使用函数组合,嵌套,实现功能更加强大的组件。
- 组件不会被实例化,整体渲染性能得到提升。
1. React Hook/Hooks是什么?
(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使用 state 以及其他的 React 特性
2. 三个常用的Hook
(1). State Hook: React.useState()
(2). Effect Hook: React.useEffect()
(3). Ref Hook: React.useRef()
3. State Hook
(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)
(3). useState()说明:
参数: 第一次初始化指定的值在内部作缓存
返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
案例
import React from 'react'
// class Demo extends React.Component {
// state = { count: 0 }
// add = () => {
// // 对象式的setState
// this.setState({ count: this.state.count + 1 })
// }
// render() {
// return (
// <div>
// <h1>当前求和为:{this.state.count}</h1>
// <button onClick={ this.add }>点我+1</button>
// </div>
// )
// }
// }
// 初始化的调用顺序不能被打乱
// useState 只能在顶层调用,不饿能在条件语句中调用,也不能在循环块中调用
// 调用的次数不能多也不能少
function Demo() {
const [Count, setCount] = React.useState(0)
const [Name, setName] = React.useState("zhangsan")
function add(){
setCount(Count+1)
}
function changeName(){
setName("set")
}
return (
<div>
<h1>当前求和为:{Count}</h1>
<h1>当前的名字为:{Name}</h1>
<button onClick={ add }>点我+1</button>
<button onClick={ changeName }>切换名字</button>
</div>
)
}
export default Demo
4. Effect Hook
(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
发ajax请求数据获取
设置订阅 / 启动定时器
手动更改真实DOM
(3). 语法和说明:
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
(4). 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
案例
案例1
import React from 'react'
import ReactDOM from 'react-dom'
// class Demo extends React.Component {
// state = { count: 0 }
// add = () => {
// // 对象式的setState
// this.setState({ count: this.state.count + 1 })
// }
// componentDidMount() {
// setInterval(() => {
// this.setState(state => ({count:state.count+1}))
// },1000)
// }
// unmount = () => {
// ReactDOM.unmountComponentAtNode(document.getElementById('root'))
// }
// componentDidMount(){
// this.timer= setInterval(() => {
// this.setState(state => ({count:state.count+1}))
// },1000)
// }
// componentWillUnmount() {
// clearInterval(this.timer)
// }
// render() {
// return (
// <div>
// <h1>当前求和为:{this.state.count}</h1>
// <button onClick={this.add}>点我+1</button>
// <button onClick={this.unmount}>点我卸载组件</button>
// </div>
// )
// }
// }
function Demo() {
const [Count, setCount] = React.useState(0)
function add(){
setCount(Count+1)
}
function unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
React.useEffect(() => {
let timer= setInterval(() => {
setCount(count => count + 1)
}, 1000)
return () => {
clearInterval(timer)
}
},[])
return (
<div>
<h1>当前求和为:{Count}</h1>
<button onClick={add}>点我+1</button>
<button onClick={unmount}>点我卸载组件</button>
</div>
)
}
export default Demo
案例2
// import React, { useState } from 'react'
import React,{Component,useState,useEffect} from 'react'
// class App2 extends Component {
// state = {
// count: 0,
// size: {
// width: document.documentElement.clientWidth,
// heigth: document.documentElement.clientHeight
// }
// }
// onResize = () => {
// this.setState({
// size: {
// width: document.documentElement.clientWidth,
// heigth: document.documentElement.clientHeight
// }
// })
// }
// componentDidMount() {
// document.title = this.state.count
// window.addEventListener('resize', this.onResize, false)
// }
// componentWillUnmount() {
// window.removeEventListener('resize', this.onResize, false)
// }
// componentDidUpdate() {
// document.title = this.state.count;
// }
// render() {
// const { count,size } = this.state
// return (
// <button
// type="button"
// onClick={()=>{this.setState({count:count+1})}}
// >
// Click ({count})
// size:{size.width}x{size.heigth}
// </button>
// )
// }
// }
function App(props) {
// 延迟初始化 (只调用一次)
const [count, setCount] = useState(0);
const [size, setSize] = useState({
width: document.documentElement.clientWidth,
heigth: document.documentElement.clientHeight
})
// 初始化的调用顺序不能被打乱
// useState 只能在顶层调用,不饿能在条件语句中调用,也不能在循环块中调用
// 调用的次数不能多也不能少
const onResize = () => {
setSize({
width: document.documentElement.clientWidth,
heigth: document.documentElement.clientHeight
})
}
useEffect(() => {
document.title = count
})
useEffect(() => {
window.addEventListener('resize', onResize, false)
return () => {
window.removeEventListener('resize', onResize, false)
}
},[])
return (
<button
type="button"
onClick={()=>{setCount(count+1)}}
>
Click ({count})
size:{size.width}x{size.heigth}
</button>
)
}
export default App;
5. Ref Hook
(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样
案例
import React from 'react'
import ReactDOM from 'react-dom'
// class Demo extends React.Component {
// state = { count: 0 }
// myRef =React.createRef()
// add = () => {
// // 对象式的setState
// this.setState({ count: this.state.count + 1 })
// }
// componentDidMount() {
// setInterval(() => {
// this.setState(state => ({count:state.count+1}))
// },1000)
// }
// unmount = () => {
// ReactDOM.unmountComponentAtNode(document.getElementById('root'))
// }
// show = () => {
// alert(this.myRef.current.value)
// }
// componentDidMount(){
// this.timer= setInterval(() => {
// this.setState(state => ({count:state.count+1}))
// },1000)
// }
// componentWillUnmount() {
// clearInterval(this.timer)
// }
// render() {
// return (
// <div>
// <input type="text" ref={this.myRef}/>
// <h1>当前求和为:{this.state.count}</h1>
// <button onClick={this.add}>点我+1</button>
// <button onClick={this.unmount}>点我卸载组件</button>
// <button onClick={this.show}>点击提示数据</button>
// </div>
// )
// }
// }
function Demo() {
const [Count, setCount] = React.useState(0)
const myRef =React.useRef()
function add(){
setCount(Count+1)
}
function unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
function show() {
alert (myRef.current.value)
}
React.useEffect(() => {
let timer= setInterval(() => {
setCount(count => count + 1)
}, 1000)
return () => {
clearInterval(timer)
}
},[])
return (
<div>
<input type="text" ref={myRef}/>
<h1>当前求和为:{Count}</h1>
<button onClick={add}>点我+1</button>
<button onClick={unmount}>点我卸载组件</button>
<button onClick={show}>点我提示数据</button>
</div>
)
}
export default Demo
import React,{PureComponent,useEffect, useState,useCallback ,useMemo,useRef} from 'react'
class Counter extends PureComponent {
speak() {
console.log( `now counter is: ${this.props.count}`)
}
render() {
const {props} = this
return (
<h1 onClick={props.onClick}></h1>
)
}
}
function App(props) {
const [count, setCount] = useState(0);
const it =useRef()
const counterRef = useRef()
// 会执行两次 一次等于3 一次从三改成其他数字时
const double = useMemo(() => {
return count*2
}, [count === 3])
useEffect(() => {
it.current = setInterval(() => {
setCount(count=>count+1)
},1000)
}, [])
useEffect(() => {
if (count >= 10) {
clearInterval(it.current)
}
})
const onClick = useCallback(() => {
counterRef.current.speak()
},[counterRef])
return (
<div>
<button
type="button"
onClick={()=>{setCount(count+1)}}
>
Click ({count})
double: ({double})
</button>
<Counter ref= {counterRef} count={double} onClick={onClick}/>
</div>
)
}
export default App;
6.自定义Hooks
案例
import React,{PureComponent,useEffect, useState,useCallback ,useMemo,useRef} from 'react'
function useCounter(count) {
const size = useSize()
return (
<h1>{count},{size.width}{size.height }</h1>
)
}
// 自定义use参数
function useCount(defaultCount) {
const [count, setCount] = useState(defaultCount);
const it =useRef()
useEffect(() => {
it.current = setInterval(() => {
setCount(count=>count+1)
},1000)
}, [])
useEffect(() => {
if (count >= 10) {
clearInterval(it.current)
}
})
return [count,setCount]
}
function useSize() {
const [size, setSize] = useState({
width: document.documentElement.clientWidth,
height:document.documentElement.clientHeight
})
const onResize = useCallback(() => {
setSize({
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
})
},[])
useEffect(() => {
window.addEventListener('resize', onResize, false)
return () => {
window.removeEventListener('resize',onResize,false)
}
}, [])
return size
}
function App(props) {
const [count, setCount] = useCount(0)
const Counter = useCounter(count)
const size = useSize()
return (
<div>
<button
type="button"
onClick={()=>{setCount(count+1)}}
>
Click ({count}),{size.width}x{size.height}
</button>
{Counter}
</div>
)
}
export default App;
版权声明:本文为weixin_50001396原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。