useReducer是useState的升级版
背景说明:
当我们在一个组件中需要设置多个state,但是多个state的关联特别的密切,比如说,当组件中存在非常的类型,日期类型,具体日期,爱好,主类别,子类别…(假设关系非常紧密,用的时候几乎都是一起拿到)
如果说明分别使用state,需要非常多的state,别人找时非常容易混乱,如果直接使用useReducer便会方便很多。
useReducer语法
const [state, dispatch] = useReducer(reducer, initialArg, init);
官网说明
useState 的替代方案。它接收一个形如
(state, action) => newState 的 reducer
,并返回当前的 state 以及与其配套的dispatch
方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)
在某些场景下,
useReducer
会比useState
更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用useReducer
还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。
Read/index.jsx
父组件
import React, { useState, useReducer } from 'react';
import List from './components/List';
import Card from './components/Card';
import Segment from '../../components/Segment';
import { CLASSIFY, DATE_TYPE } from '../../util/constant';
import './index.scss';
const getItem = (state, action) => {
console.log('gettt', state, action);
switch (action?.type) {
case 'seg1':
return {
...state,
segText1: action?.data?.text,
segVal1: action?.data?.value,
}
case 'seg2':
return {
...state,
segText2: action?.data?.text,
segVal2: action?.data?.value,
}
}
}
const initState = {
segText1: '',
segVal1: '',
segText2: '',
segVal2: ''
}
function Read(pros) {
console.log('redner-read');
const [list1, setList1] = useState(0);
const [card1, setCard1] = useState(0);
const [card2, setCard2] = useState(0);
const [state, dispatch] = useReducer(getItem, initState)
const cardGetCount1 = (value) => {
setCard1(value)
}
const cardGetCount2 = (value) => {
setCard2(value)
}
const listGetCount1 = (value) => {
setList1(value)
}
const getSeg1 = (item) => {
dispatch({ type: 'seg1', data: item })
}
const getSeg2 = (item) => {
dispatch({ type: 'seg2', data: item })
}
console.log('segment', state);
return (
<>
<div className='top_READ'>
<h2> Read</h2>
<div>
<Segment
option={CLASSIFY}
onChange={getSeg1}
/>
<Segment
option={DATE_TYPE}
onChange={getSeg2}
/>
</div>
<List
value1={list1}
listGetCount1={listGetCount1}
/>
<br />
<Card
value1={card1}
value2={card2}
cardGetCount1={cardGetCount1}
cardGetCount2={cardGetCount2}
/>
</div>
</>
)
}
export default Read;
Segment/index.jsx
子组件
import React, { useState } from "react";
import './index.scss';
export default function Segment(props) {
const {
option = [],
value,
onChange,
} = props;
// 当option为[],不执行
const [val, setVal] = useState(value || option?.length ? option[0]?.value : '');
const handleItem = (item) => {
return () => {
setVal(item?.value);
onChange(item)
}
}
if (!option?.length) {
return null;
}
console.log('render--Segment',);
return (
<div className="segment">
{
option?.map((v, index) => {
return (
<button
key={v?.text + index}
className={`item ${val === v?.value ? 'activeItem active' : ''}`}
onClick={handleItem(v)}
>
{v?.text}
</button>
)
})
}
</div>
)
}