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>
)
}
网友评论