我的应用程序UI状态开始变得有些复杂,有许多useStateState,所以我创建了一个useStateMate钩子(对不起,这个俗气的名字(,如下所示。这种方法有什么陷阱吗?
import { useState } from 'react';
const stateUpdater = (state, updater) => (property, value) => updater({ ...state, [property]: value })
export default function useStateMate(initialState) {
const [state, updater] = useState(initialState);
const setState = stateUpdater(state, updater);
return [state, setState]
}
用法:(UI 状态由 useStateMate 管理,存储数据不是(
import React from 'react'
import useStateMate from './hooks/useStateMate'
import { useStore } from 'outstated'
import dataStore from './stores/mock-data-store'
const initialState = {
selectedMarkerId: null,
selectedDrivers: [],
mapEditMode: { on: true, id: null, tool: null },
quickChange: null,
filter: '',
groupBy: 'PostalCode,City',
paths: new Map(),
working: false
}
function App(props) {
const [store, dispatch] = useStore(dataStore);
const [state, setState] = useStateMate(initialState);
const { selectedMarkerId, selectedDrivers, mapEditMode, quickChange, filter, groupBy, paths, working } = state;
...
我采取的另一种方法是使用Reducer,但不喜欢必须更新状态,比较:
dispatch({type: ..., value: ...})
跟
setState('property', value)
你可以简单地使用单个useState
并将状态作为对象(就像我们在类组件的美好时代一样(。但是如果你遵循这条路,最好(也是 React 人员推荐的(使用 useReducer。不要被这里的命名所迷惑 - 它与 Redux 无关,尽管典型的 Redux 化简器也可以传递给useReducer
。
当您有复杂的时,
useReducer
通常比useState
更可取 涉及多个子值或下一个状态时的状态逻辑 取决于前一个。useReducer
还可以让您优化 触发深度更新的组件的性能。
考虑一个例子:
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter({initialState}) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}