Hook
Hook 是 React 16.8 的新增特性。它可以让你在函数组件中使用一些和类组件相似的功能如state状态的设置、ref获取函数组件、生命周期等
useState
import {useState} from 'react'
说明
返回一个 state,以及更新 state 的函数。
let [value,setValue] = useState('')
// value 状态名称 setValue 更新状态方法 useState( 初始化值 )
useState可以让函数组件使用和类组件相同的state状态(数据),在其中的value为定义的状态名,在函数组件中可以全局使用,setValue是更新状态的由useState生成专门针对对应状态的方法,其功能如同类组件的setState,会引发组件的更新阶段,异步进行。
useState( 初始化值 ) 其中的初始化一般为Number,String等栈内存基本变量,如果初始化为Object、数组或new对象等堆内存变量则会发生问题。
setValue使用
setValue( ‘复制操作’ )
setValue(val=>val+'回调函数简写')
setValue(val=>{return val+"return新值"})
render(
return <div> <button onclick={
setValue('render使用')
}><button/>{ value } </div>
)
解决Object、数组保存的问题
在函数组件中,拥有和类组件在shouldComponentUpdate一样的浅对比,其次在函数组件中,没有生命周期的功能,在后面的useEffect中才可以做到类生命周期。我们不容易做到对于Object、数据等进行深对比,所以在useState中定义的对象或数组可以在对应的setState中发生更新但,因为默认浅对比对比Object时只会对比其中的地址所以不会触发更新,也就不会让页面进行更新。 下面是进行针对这些特殊变量进行的可以触发更新的操作
async function addlist(){
await setonObj( oldOnObj=>{ // 对象更新
oldOnObj.value = '更新'
let obj = {...oldOnObj} // 结构 赋予新地址
oldOnObj = null // 清除内存
return obj
})
await setList( ()=>{ // 数组更新
list.push(‘更新’)
let list1 = [...list] // 结构赋予 新地址
list = null // 清内存
return list1
})
}
通过ES6的结构,获取新的对象,并把原来的对象内存销毁 使得在函数组件在浅对比的时候,可以进行重新页面渲染
useEffect
import {useEffect} from 'react'
说明
该 Hook 接收一个包含命令式、且可能有副作用代码的函数。
三个生命周期的组合 componentDidmount 、componentDIdUpdate、
componentUnMount
在函数组件主体内(这里指在 React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。 useEffect提供了这些副作用操作的可能
监听数据
useEffect(()=>{
},[]) // 传两个 则等同于 DidMount 一次
useEffect(()=>{
}) // 传一个 则等同于 DidMount + DidUpdate 多次
useEffect(()=>{
},[count]) // count属性改变监听
通过传入一个变量,可以在useEffect中监听这个变量的变化,如果为[] 则表示监听所有的在useState中的变量。
副作用
useEffect(()=>{
const div_ = document.querySelector('div') // 真实DOM操作
fetch('http//1****') // 数据请求
div_.onclick = () => {} // 订阅操作(事件添加)
setTimeout(() => { // 定时器
}, 0);
})
## useContext
```javascript
import {useContext} from 'react'
说明
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值
祖宗组件输出信息
const obj = {
money:20000
}
const moneyContext = React.createContext(obj .money);
constructor(props) {
render(){
const { money } = this.state
return <div>
<moneyContext.Provider value={money}>
<One></One>
</moneyContext.Provider>
</div>
}
}
export default App;
孙子组件接收信息
export default function newcomp2(){
const {money}= useContext(moneyContext );
render() {
return (
<div>
{money}
</div>
)
}
}
useReducer
import {useReducer} from 'react'
说明
const [state, dispatch] = useReducer(reducer, initialArg, init);
// state 状态 dispatch 状态逻辑 reducer 函数方法 initialArg 初始化值 init
useReducer是useState的替代方案,使得定义的状态功能更完善。
在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。
const [value,dispath] = useReducer(change,{
id:0,
value:''
})
function change(state,action){
state.id++
state.value = action.type
return state
}
return (
<div>
<button onClick={()=>{dispath({type: 5})}}>+</button>
</div>
)
跳过 dispatch
同 useState 一样 是浅对比,对象改变不会触发页面渲染,可以通过改变一个已存在的普通状态来达到页面刷星的效果
如果 Reducer Hook 的返回值与当前 state 相同,React 将跳过子组件的渲染及副作用的执行。(React 使用 Object.is 比较算法 来比较 state。)
useDebugValue
import {useDebugValue} from 'react'
说明
useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。
其需要在自定义Hook中使用
自定义Hook
import { useState, useEffect,useDebugValue } from 'react';
export default function useFriendState(flag) {
const [isOnline, setIsOnline] = useState(null);
useEffect(()=>{setIsOnline(flag)})
useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline ;
}
import React from 'react'
import useFriendState from './useFriendState'
export default function A(props) {
let op = 15;
useFriendState(op)
props.give()
return (
<div>
{props.number}
</div>
)
}