Hook
注意hook只能在函数组件中使用
useState()
作用:const res = useState(initState) 状态的改变
返回值:是一个array:[state, changeNum]
写法:const [ num, changeNum ] = useState(0)
import React,{useState} from 'react'
// console.log("useState=",useState)
/*
useState= ƒ useState(initialState) {
var dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
*/
function UseState() {
const [num, changeNum] = useState(0)
return (
<div>
<div>{num}</div>
<button onClick={() => {
changeNum(num + 1)
}}>点我数量加1:{num}</button>
</div>
)
}
// 使用useState 实现了在函数组件中的状态改变
export default UseState
useEffect()
作用:实现类组件中生命周期的函数功能
用法:useEffect(callback, 依赖)
import React, { useEffect, useState } from 'react'
// console.log("useEffect=", useEffect)
/*
useEffect= ƒ useEffect(create, deps) {
var dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, deps);
}
*/
function UseEffect() {
const [num, changeNum] = useState(0)
const [qty, changeQty] = useState(1)
// 注意:以下的useEffect 一进入页面初始化都会执行,但是必须等render渲染之后,可以根据后面的依赖和return后再执行
// 1、没有指定依赖:实现componentDidMount 和 componentDidUpdate
// 进入组件执行下面代码, 更新组件执行下面代码
useEffect(function () {
// 这里的代码在数据挂载后执行,在此可执行ajax请求,dom操作
console.log('useEffect没有指定依赖')
})
// 2、指定空依赖:实现componentDidMount
// 进入组件执行下面代码,后面就不再执行下面代码
useEffect(function () {
// 这里的代码在数据挂载后执行,在此可执行ajax请求,dom操作
console.log('useEffect空依赖')
}, [])
// 3、指定某个依赖:实现shouldComponentUpdate的效果
// 只有qty的 更新时,才执行这里的代码,不是qty更新,不执行下面代码
useEffect(function () {
// 这里的代码在数据挂载后执行,在此可执行ajax请求,dom操作
console.log('useEffect的qtyChange')
}, [qty])
// 4、指定返回值: 实现componentWillUnmont 的效果
useEffect(function () {
// 进入组件先执行下面的代码,而return 后面的是在组件被销毁后执行
console.log('useEffect,return返回值')
return function () {
// 这里的代码在组件被销毁后执行
// 比如 取消ajax的请求,关闭定时器
console.log('指定返回值,实现componentWillUnmont')
}
})
return (
<div>
<h1>useEffect()</h1>
<button onClick={() => {
changeNum(num + 1)
}
}>点我num:{num} </button>
<button onClick={() => {
changeQty(qty + 1)
}}>点我qty:{qty}</button>
</div>
)
}
/*
类组件的刷新只执行render
函数组件会从头到尾执行一遍所有代码
注意点: 函数组件必须等render渲染之后,才会执行上面的代码(根据生命周期图可知)useEffect(), dom节点这时也可以拿到
*/
export default UseEffect
useMemo()
作用:用来执行一些大量计算和花费大量时间的操作
用法:useMemo(callback, [xxx])
import React, { useState, useMemo } from 'react'
function UseMemo() {
const [num, changeNum] = useState(1)
const [qty, changeQty] = useState(1)
// 当需要大量的计算时,用 useMemo
// 而num依赖 ,只有当num更新时,才执行下面代码
const total = useMemo(function () {
console.log('计算总和')
let total = 0
for (let i = 0; i < num * 10000; i++) {
total += i
}
return total
}, [num])
return (
<div>
<h1>useMemo()</h1>
总和:{total}
<button onClick={() => {
changeNum(num + 1)
}}>num:{num}</button>
<button onClick={() => {
changeQty(qty + 1)
}}>qty:{qty}</button>
</div>
)
}
export default UseMemo
useCallback()
用法:useCallback(callback, [xxx])
import React, {
useCallback,
useMemo,
useState
} from 'react'
const callbackList = []
function UseCallback() {
const [num, changeNum] = useState(1)
const [qty, changeQty] = useState(1)
const handleNum = useCallback(function () {
changeNum(num + 1)
}, [num])
//下面的代码每次更新组件,会创建一个函数
const handleQty = function () {
changeQty(qty + 1)
}
callbackList.push(handleNum)
console.log(callbackList, callbackList[0] === callbackList[1])
// 使用useMemo 实现useCallback的功能
// const handleNum = useMemo(function () {
// return function () {
// changeNum(num + 1)
// }
// },[num])
return (
<div>
useCallback()
<button onClick={handleNum}>num:{num}</button>
<button onClick={handleQty}>qty:{qty}</button>
</div>
)
}
/**
* 第一次点击 handleQty 时,打印的为true
* 说明handleNum 是从缓存里面拿的 handleNum 是用 useCallback
*
* 第二次点击 handleNum 时,打印的为false
* 说明每次更新组件,会创建一个函数,因为handleNum 发生变化
*
*/
export default UseCallback
useReducer()
作用:实现简单的reducer功能,在组件间实现数据共享
用法:const [state, dispatch] = useReducer(reducer, initState)
import React, { useCallback, useMemo, useReducer } from 'react'
const initState = [
{ name: "goods1", price: 98, qty: 2 },
{ name: "goods2", price: 198, qty: 2 },
{ name: "goods3", price: 998, qty: 1 },
]
function reducer(state, action) {
switch (action.type) {
case 'add':
return [action.goods, ...state]
case 'remove':
return state.filter(item => item.name !== action.name)
case 'changeQty':
return state.map(item => {
if (item.name === action.name) {
item.qty = action.qty
}
})
case 'clear':
return []
default:
throw new Error('type error')
}
}
function UseReducer() {
const [state, dispatch] = useReducer(reducer, initState)
const clearCart = useCallback(function () {
const action = { type: 'clear' }
dispatch(action)
}, [])
// 加空依赖:只执行一次
const addToCart = useCallback(function (name) {
// 判断是否存在
// 存在:修改数量
// 否则:添加商品
// console.log("state",state.length)
// 添加商品
let action = { type: 'add', goods: { name: "goods" + (state.length + 1), price: 198, qty: 2 }, }
dispatch(action)
}, [state])
// 加自定义依赖:当数据改变时,才更新
// 计算总价 大量计算时使用 useMemo()
const total = useMemo(() => {
return state.reduce((prev, item) => prev + item.price * item.qty, 0)
}, [state])
// 加自定义依赖:当数据改变时,才更新
// 删除商品
const removeItem = useCallback(function (name) {
const action = { type: 'remove', name }
dispatch(action)
}, [])
// 加空依赖:只执行一次
return (
<div>
<h1>useReducer()</h1>
<ul>
{
state.map(item => <li key={item.name}>
<h4>{item.name}</h4>
<p className="price">{item.price}×{item.qty}</p>
<button onClick={removeItem.bind(this, item.name)}>删除</button>
</li>)
}
</ul>
{/* <div style={{ textAlign: 'right' }}>总价:{total}</div> */}
<button onClick={clearCart}>清空购物车</button>
<button onClick={addToCart.bind(null, 'goods3')}>添加</button>
</div>
)
}
export default UseReducer