Hooks
-
Hook是 React16.8 的新特性,可以在不使用类组件的情况下,使用state以及其他的React特性;-
Hook是完全可选的,无需重写任何已有代码就可以在一些组件中尝试Hook - 于React16.8.0发布,100%向后兼容,
Hook不包含任何破坏性改动.
-
- React也没有计划移除class类组件,而且Hook不会影响对React的理解,它为已知的React概念提供了更直接的API:
props、state、context、refs、生命周期 - Hook解决的问题
-
函数式组件不能使用state:函数式组件比类组件更简洁好用,而
Hook让它更加丰富强大; -
副作用问题:诸如数据获取、订阅、定时执行任务、手动修改
ReactDOM这些行为都可以称为副作用;而Hook的出现可以使用useEffect来处理这些副作用; - 有状态的逻辑重用组件
-
复杂的状态管理:之前通常使用
redux、dva、mobx这些第三方状态管理器来管理复杂的状态,而Hook可以使用useReducer、useContext配合实现复杂的状态管理; - 开发效率和质量问题:函数式组件比类组件简洁,效率高,性能也好。
-
函数式组件不能使用state:函数式组件比类组件更简洁好用,而
常用的Hooks
-
useState:组件状态管理的钩子
useState能使函数组件能够使⽤state
import { useState } from 'react'
const [state, setState] = useState(initState)
-
state:管理组件的状态; -
setState:更新state的方法,方法名不可更改!
3.initState:初始的state,可以是任意的数据类型(只在初次渲染时有效,二次渲染时会被忽略),也可以是回调函数,但函数必须有返回值。
函数式组件实现计数器
import { useState } from 'react'
export default function App() {
const [count, setCount] = useState(1) // 初始值1
return (
<div>
<div>点击了{ count }次</div>
<button onClick={()=>setCount(count+1)}>点击</button>
</div>
)
}
-
useEffect(callback, array):副作用处理的钩子
- 数据获取、订阅、定时执⾏任务、⼿动修改
ReactDOM这些⾏为都可以称为副作⽤。⽽useEffect就是为了处理这些副作⽤⽽⽣的; -
useEffect也是componentDidMount()、componentDidUpdate()、componentWillUnmount()、这几个生命周期方法的统一。React 会等待浏览器完成画面渲染之后才会延迟调用 useEffect;
基本使用
import { useEffect } from 'react'
useEffect(()=>{
......//副作用处理
return ()=>{
......//清理副作用的清除函数
}
}, [])
callback:回调函数,作用是处理副作用的逻辑
callback:可以返回一个函数,用作清理副作用;
array(可选参数):数组,⽤于控制useEffect的执⾏分三种情况
- 空数组,只会执⾏⼀次(即初次渲染
render),相当于componentDidMount - ⾮空数组,
useEffect会在数组发⽣改变后执⾏
① 如果里面是常量 : 和空数组一样,只执行一次
② 如果里面是变量 : 每次都会执行 - 不填array这个数组,
useEffect每次渲染都会执⾏
-
useContext():同一个父组件的后台组件之间的全局数据共享;
-
context就是⽤来更⽅便的实现全局数据共享的,但是由于他并不是那么好⽤,所以我们⼀般会使⽤第三⽅状态管器来实现全局数据共享
- redux
- dva
- mobx
2.useContext(context)是针对context上下⽂提出的⼀个Hooks提出的⼀个API,它接受React.createContext()的返回值作为参数,即context对象,并返回最近的context
- 使⽤
useContext是不需要再使⽤Provider和Consumer的 - 当最近的
context更新时,那么使⽤该context的hook将会重新渲染
父组件js代码
import React, { useContext } from 'react'
import UcChild from './ucChild'
//创建context对象,并暴露出去
//这里的数据也可以直接从store里拿
// import {james} from './store'
export const Context = React.createContext({ name: '詹姆斯', age: 18 })
export default function UseContext() {
const ctx = useContext(Context)
console.log(ctx)
return (
<div>
<p>我是{ctx.name},今年{ctx.age}岁</p>
<UcChild></UcChild>
</div>
)
}
子组件代码
import React, { useContext } from 'react'
import {Context} from './index' // 把父组件暴露出来的数据引入
export default function UseContext() {
const ctx = useContext(Context)
return (
<div>
<p>我是{ctx.name},今年{ctx.age}岁</p>
</div>
)
}
-
useReducer():useState的一个增强体,可用于处理复杂的状态管理,灵感来源于Redux的reducer;
-
useReducer()完全可以取代useState(),只是对于简单的状态管理,useState()比较好用;
// useState的使用方法
const [state, setState] = useState(initState)
// useReducer的使用方法
const [state, dispatch] = useReducer(reducer, initState, initAction)
参数介绍
reducer:一个函数,根据action(action就是dispatch传入的参数)状态处理并更新state;
initState:初始化的state;
initAction:(不常用)useReducer()初次执行时被处理的action;
返回值介绍
state:状态值;
dispatch:更新state的方法,接收action作为参数,当它被调用时,reducer函数也会被调用,同时根据action去更新state,action是一个描述操作的对象,dispatch({type: 'add'})
-
useReducer只需要调⽤dispatch(action)⽅法传⼊action即可更新state,使⽤如下
//dispatch是⽤来更新state的,当dispatch被调⽤的时候,reducer⽅法也会被调⽤,同时根据action的传⼊内容去更新state action是传⼊的⼀个描述操作的对象
dispatch({type:'add'})
-
reducer是redux的产物,他是⼀个函数,主要⽤于处理action,然后返回最新的state,可以把reducer理解成是action和state的转换器,他会根据action的描述去更新state,
使⽤例⼦:
(state,action) => Newstate
示例代码
import React, { useReducer } from 'react'
const initState = { count: 0 } //创建一个初始值
//这是useReducer()参数里面的reducer,是一个实现方法函数
const reducer = (state, action) => {
//根据dispatch传入的action去更新state
switch (action.type) {
//党传入的action的type是reset时,代表重置,就返回初始值state,依次类推
case 'reset':
return initState;
case 'add':
return { count: state.count + 1 };
case 'red':
return { count: state.count - 1 };
///不复合以上类型,返回原来的state
default:
return state
}
}
export default function UseReducerCompt() {
//使用useReducer
const [state, dispatch] = useReducer(reducer, initState)
return (
<div>
<p>当前数量为 : {state.count}</p>
<p>
<button onClick={() => dispatch({ type: 'reset' })}>重置</button>
<button onClick={() => dispatch({ type: 'add' })}>加一</button>
<button onClick={() => dispatch({ type: 'red' })}>减一</button>
</p>
</div>
)
}