MapDispatchToProps 在父组件中导致 Typescript 错误,期望 Actions 作为 props 传递
MapDispatchToProps causes Typescript Error in parent-component, expecting Actions to be passed as props
在我的子组件中,我正在定义 MapDispatchToProps,将它们传递给连接并相应地定义一个在 React.Component Props 接口中扩展的接口 PropsFromDispatch。现在在我的父组件中,Typescript 告诉我它缺少我在 PropsFromDispatch 中定义的属性。
这似乎并不完全荒谬,因为我将它们定义为 React.Component Props 接口的一部分,但是我希望 'connect' 以与它相同的方式处理它照顾我的 PropsFromState,我也不必将其从父组件传递到子组件,而是从 State 映射到 Props。
/JokeModal.tsx
...
interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}
...
const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}
interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}
...
export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);
/Parent.tsx
...
button = <JokeModal isOpen={false} renderButton={true} />
...
在 /Parent.tsx 的这一行中,Typescript 现在告诉我:
Type '{ isOpen: false; renderButton: true; }' is missing the
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)
有趣的是,我可以通过删除 MapDispatchToProps 并将动作直接传递到连接中(包括已经在动作创建者中的分派)来完全避免错误:
export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);
尽管如此,我想知道如何在这里使用 MapDispatchToProps 以及为什么 Typescript 期望我将这些操作传递给子组件?
很高兴听到您的建议!
我能够重现您的问题,问题显然出在 source code 中 mapDispatchToProps
函数的类型签名中,您可以看到它有一个类型参数 Action = AnyAction
export interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T
}
你的问题的解决方案是将 Dispatch<any>
更改为 Dispatch<AnyAction>
:
const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch
请注意,由于您使用的是 redux-thunk,类型系统可能不允许您在 thunk 上调用 dispatch
,因此您可能不得不通过调用
作弊
clearErrors: () => dispatch<any>(clearErrors());
或者使用 ThunkDispatch
和 ThunkAction
的相当冗长的输入。我在这里有一个这样输入的例子:ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.
在我的子组件中,我正在定义 MapDispatchToProps,将它们传递给连接并相应地定义一个在 React.Component Props 接口中扩展的接口 PropsFromDispatch。现在在我的父组件中,Typescript 告诉我它缺少我在 PropsFromDispatch 中定义的属性。
这似乎并不完全荒谬,因为我将它们定义为 React.Component Props 接口的一部分,但是我希望 'connect' 以与它相同的方式处理它照顾我的 PropsFromState,我也不必将其从父组件传递到子组件,而是从 State 映射到 Props。
/JokeModal.tsx
...
interface Props extends PropsFromState, PropsFromDispatch {
isOpen: boolean
renderButton: boolean
}
...
const mapDispatchToProps = (dispatch: Dispatch<any>):
PropsFromDispatch => {
return {
tellJoke: (newJoke: INewJoke) => dispatch(tellJoke(newJoke)),
clearErrors: () => dispatch(clearErrors())
}
}
interface PropsFromDispatch {
tellJoke: (newJoke: INewJoke) => void
clearErrors: () => void
}
...
export default connect(mapStateToProps, mapDispatchToProps)(JokeModal);
/Parent.tsx
...
button = <JokeModal isOpen={false} renderButton={true} />
...
在 /Parent.tsx 的这一行中,Typescript 现在告诉我:
Type '{ isOpen: false; renderButton: true; }' is missing the
following properties from type 'Readonly<Pick<Props, "isOpen" |
"renderButton" | "tellJoke" | "clearErrors">>': tellJoke, clearErrors
ts(2739)
有趣的是,我可以通过删除 MapDispatchToProps 并将动作直接传递到连接中(包括已经在动作创建者中的分派)来完全避免错误:
export default connect(mapStateToProps, { tellJoke, clearErrors })(JokeModal);
尽管如此,我想知道如何在这里使用 MapDispatchToProps 以及为什么 Typescript 期望我将这些操作传递给子组件?
很高兴听到您的建议!
我能够重现您的问题,问题显然出在 source code 中 mapDispatchToProps
函数的类型签名中,您可以看到它有一个类型参数 Action = AnyAction
export interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T
}
你的问题的解决方案是将 Dispatch<any>
更改为 Dispatch<AnyAction>
:
const mapDispatchToProps = (dispatch: Dispatch<AnyAction>): PropsFromDispatch
请注意,由于您使用的是 redux-thunk,类型系统可能不允许您在 thunk 上调用 dispatch
,因此您可能不得不通过调用
clearErrors: () => dispatch<any>(clearErrors());
或者使用 ThunkDispatch
和 ThunkAction
的相当冗长的输入。我在这里有一个这样输入的例子:ThunkDispatch and the corresponding ThunkAction. Note that I use typesafe-actions.