应该如何使用 useDispatch 来强制类型检查?



我对使用useDispatch的好处和最佳实践感到困惑。

目前,我通过导出bindActionCreators的结果来抽象对我的商店的访问(见下文(,该结果允许使用我的组件中的语句进行受控访问,例如

import {counterActions} from "./store"
//...
counterActions.reset()

对参数和结果进行完整类型检查,并对各个操作进行代码完成。

但是如果我改用useDispatch

import { useDispatch } from "react-redux"
const dispatch = useDispatch()
// ...
dispatch({type: "RESET"})

当我调用dispatch时,我没有得到任何类型或参数检查,并且可以轻松输入废话,例如

dispatch({junk: "GARBAGE", morejunk: "MOREGARBAGE"})

除非我在我的组件中明确注释类似的东西

import { CounterAction } from "../store"
// ...
const dispatch: (action: CounterAction) => void = useDispatch()

或者在我的商店中创建一个包装器,

如下所示
export function useMyDispatch(): (action: CounterAction) => void {
return useDispatch()
}

然后在我的组件中使用它。

为什么useDispatch比我的counterActions好?有没有我误解或遗漏的useDispatch成语?


商店:

import { createStore } from "redux"
import { bindActionCreators } from 'redux'

interface CounterState {
count: number;
}
type CounterAction =
| { type: 'INCREMENT'; step: number }
| { type: 'RESET' }
const initialState: CounterState = {count: 0}
const counterReducer = (state = initialState, action: CounterAction): CounterState => {
switch (action.type) {
case 'INCREMENT':
return {...state, count: state.count + action.step}
case "RESET":
return {...state, count: 1}
default:
return state
}
}
// Use only for Provider
export const store = createStore(counterReducer)
const increment = (step: number = 1): CounterAction  => ({ type: "INCREMENT", step: step })
const reset = (): CounterAction => ({ type: "RESET" })
export const counterActions = bindActionCreators(
{ increment, reset },
store.dispatch
)

您可以创建一个类型化的自定义钩子:

type Dispatch = <TReturnType>(action: Actions) => TReturnType;
const useTypedDispatch = () => useDispatch<Dispatch>();

其中Actions是您所有可用操作的联合,例如问题中的CounterAction。您可以将其用作:

const dispatch = useTypedDispatch()

相关内容

  • 没有找到相关文章

最新更新