如在上一篇文章里那个问题: 说一下常用的hooks
里能够回答出 useReducer&useContext实现状态管理
, 应该会加分吧. (猜测的, 没经过试验哈哈)
useReducer
还是上一篇中的例子
function TestReducer() {
const reducer = (state, action) => {
switch (action) {
case 'add':
return state + 1
case 'double':
return state * 2
}
}
const [count, dispatch] = useReducer(reducer, 0)
return (
<div>
{count}
<button onClick={() => dispatch('add')}>点击添加</button>
<button onClick={() => dispatch('double')}>点击*2</button>
</div>
)
}
useReducer
是一个利用action提供的信息将state
从A转换到B的一个纯函数
- 语法:(state, action) => newState
- Immutable:每次都返回一个newState, 永远不要直接修改state对象
- Action:一个常规的Action对象通常有type和payload(可选)组成
type: 本次操作的类型,也是 reducer 条件判断的依据
payload: 提供操作附带的数据信息
- state统一维护, 更容易复用代码
- 表现和业务分离,what和how分开, 代码更加清晰明了
useContext
Context
的作用就是对它所包含的组件树提供全局共享数据的一种技术
useContext
的使用方法如下
父组件中
import React, { useState , createContext } from 'react';
const CountContext = createContext()
function Example(){
const [ count , setCount ] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={()=>{setCount(count+1)}}>click me</button>
<CountContext.Provider value={count}>
</CountContext.Provider>
</div>
)
}
export default Example;
父组件下的层级组件中
function Counter(){
const count = useContext(CountContext)
//就可以直接使用了
return (<h2>{count}</h2>)
}
useReducer&useContext实现状态管理
- useReducer可以实现状态管理
- useContext可以实现数据传递
二者结合就可以实现类似redux数据管理模式
主要思想就是
- 在reducer函数中更改state
- 将更改state的dispatch函数作为context的参数传递给子组件
- 在子组件需要改变state的地方调用dispatch即可
下面用这个方式实现了一个简易的状态管理
//index.js
import React, { useReducer, useContext, createContext } from 'react'
import Info from './components/Info'
import Input from './components/Input'
export const InfoContext = createContext({})
const reducer = (state, action) => {
switch (action.type) {
case 'add':
return [
...state,
{
value: action.payload.value,
},
]
case 'delete':
return state.filter((v) => v.value != action.payload.value)
}
}
const initState = [
// {
// name:'',
// age:0,
// }
]
function Note() {
const [items, dispatch] = useReducer(reducer, initState)
return (
<InfoContext.Provider value={{ items, dispatch }}>
<Info></Info>
<Input></Input>
</InfoContext.Provider>
)
}
export default Note
//input.js
import React, { useContext } from 'react'
import { InfoContext } from '..'
function Input() {
const context = useContext(InfoContext)
const { dispatch } = context
return (
<div>
<div>
姓名:
<input
placeholder={'姓名'}
onKeyPress={(e) => {
console.log(e)
if (e.charCode === 13) {
dispatch({
type: 'add',
payload: { value: e.currentTarget.value },
})
}
}}
/>
</div>
</div>
)
}
export default Input
//info.js
import React, { useContext } from 'react'
import { InfoContext } from '..'
function Info() {
const context = useContext(InfoContext)
const { items, dispatch } = context
return (
<div>
{items.map((v) => {
return (
<div>
<p>{v.value}</p>
<button
onClick={() => {
dispatch({
type: 'delete',
payload: { value: v.value },
})
}}
>
点击删除
</button>
</div>
)
})}
</div>
)
}
export default Info