全面掌握 React — useReducer
2019-06-03 本文已影响23人
zidea
react
在 hooks 中提供了的 useReducer 功能,可以增强 ReducerDemo 函数提供类似 Redux 的功能,引入 useReducer 后,useReducer 接受一个 reducer 函数作为参数,reducer 接受两个参数一个是 state 另一个是 action 。然后返回一个状态 count 和 dispath,count 是返回状态中的值,而 dispatch 是一个可以发布事件来更新 state 的。
import React,{useReducer} from 'react'
export default function ReducerDemo() {
const [count, dispath] = useReducer((state,action)=> {
//...
}, 0);
return (
<div>
<h1 className="title">{count}</h1>
</div>
)
}
- 在 useReducer 传入 reducer 函数根据 action 来更新 state,如果 action 为 add 正增加 state 也就是增加 count。
在 button 中调用 dispatch 发布 add 事件,发布 add 事件后就会在 reducer 根据其类型对 state 进行对应操作,更新 state。
export default function ReducerDemo() {
const [count, dispath] = useReducer((state,action)=> {
if(action === 'add'){
return state + 1;
}
return state;
}, 0);
return (
<div>
<h1 className="title">{count}</h1>
<button className="btn is-primary"
onClick={()=> dispath('add')}
>Increment</button>
</div>
)
}
下面的代码并不没有什么特别,只是在上面代码基础进行巩固,大家可以自己阅读一下。
import React,{useReducer} from 'react'
export default function ReducerDemo() {
const [count, dispath] = useReducer((state,action)=> {
switch(action){
case 'add':
return state + 1;
case 'sub':
return state - 1;
default:
return state;
}
}, 0);
return (
<div>
<h1 className="title">{count}</h1>
<button className="btn is-primary"
onClick={()=> dispath('add')}
>Increment</button>
<button className="btn is-warnning"
onClick={()=> dispath('sub')}
>Decrement</button>
</div>
)
}
在下面的代码中 action 不再是字符串而变成对象,通过 type 来表示 action 类型,然后通过 name 来带来更多的信息。其实这些代码虽然变得复杂但是本质和上面分享内容并没有什么不同。
import React,{ useReducer,useRef } from 'react'
export default function ShoppingList() {
const inputRef = useRef();
const [items, dispatch] = useReducer((state,action)=> {
switch(action.type){
case 'add':
return [...state,
{
id:state.length,
name:action.name
}]
}
},[])
function handleSubmit(event){
event.preventDefault();
dispatch({
type:'add',
name:inputRef.current.value
});
inputRef.current.value = '';
}
return (
<>
<form onSubmit={handleSubmit}>
<input ref={inputRef}/>
</form>
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</>
)
}
这里值得说一下就是 ...state 这是每一次我们需要 copy 一个 state 然后修改 state 而不是在 state 原有对象进行修改。这就是 immutable 数据吧。
import React,{ useReducer,useRef } from 'react'
export default function ShoppingList() {
const inputRef = useRef();
const [items, dispatch] = useReducer((state,action)=> {
switch(action.type){
case 'add':
return [...state,
{
id:state.length,
name:action.name
}]
case 'remove':
return state.filter((_,index) => index != action.index)
case 'clear':
return [];
default:
return state;
}
},[])
function handleSubmit(event){
event.preventDefault();
dispatch({
type:'add',
name:inputRef.current.value
});
inputRef.current.value = '';
}
return (
<>
<form onSubmit={handleSubmit}>
<input ref={inputRef}/>
</form>
<button
className="button is-danger"
onClick={
() => dispatch({type:'clear'})
}>clear</button>
<ul>
{items.map((item,index) => (
<li className="section" key={item.id}>{item.name}
<button className="button" onClick={
() => dispatch({type:'remove',index})
}>X</button>
</li>
))}
</ul>
</>
)
}
react-dev