我正在使用redux和typescript作为我当前的webapp .
定义组件的道具的最佳实践是什么,它通过 @connect
接收redux-actions,还有来自父级的道具?例:
// mychild.tsx
export namespace MyChildComponent {
export interface IProps {
propertyFromParent: string;
propertyFromRedux: string; // !!!! -> This is the problem
actionsPropertyFromRedux: typeof MyReduxActions; // !!!! -> And this
}
}
@connect(mapStateToProps, mapDispatchToProps)
export class MyChildComponent extends React.Component <MyChildComponent.IProps, any> {
... react stuff
}
function mapStateToProps(state: RootState) {
return {
propertyFromRedux: state.propertyFromRedux
};
}
function mapDispatchToProps(dispatch) {
return {
actionsPropertyFromRedux: bindActionCreators(MyReduxActions as any, dispatch)
};
}
// myparent.tsx
export class MyParentComponent extends React.Component <MyParentComponent.IProps, any> {
... react stuff
render(){
// typescript complains, because I am not passing `propertyFromRedux`!
return <div><MyChildComponent propertyFromParent="yay" /></div>;
}
}
我看到它有两个解决方案 .
-
只需通过我的整个应用程序传递操作和状态 . 但这意味着即使只是一些小的子组件必须改变,我的整个应用程序也会被重新渲染 . 或者是在所有商店更改中收听我的顶级组件的redux方式?然后我必须在
shouldComponentUpdate
内写出很多逻辑,用于没有扁平物体的道具 . -
将
IProps
中的参数设置为MyChildComponent
可选,如下所示:
// mychild.tsx
export namespace MyChildComponent {
export interface IProps {
propertyFromParent: string;
propertyFromRedux?: typeof MyAction; // This is the problem
}
}
还有另外一种方法吗?上述两种方式在我眼中看起来都太乱了 .
1 回答
你需要拆分你的道具 - 你需要
DispatchProps
,StateProps
和OwnProps
类型 . 你'll also have to use TypeScript'的泛型与connect
DispatchProps
是您的动作创作者 .StateProps
是你的状态道具(duh) - 这些来自mapStateToProps
- 该函数的返回类型应与此类型匹配 .OwnProps
是您的组件接受(也许是预期)的道具 . 可选的道具应在界面中标记为可选 .我这样做的方式(没有装饰器,但我相信它适用于此)是
我认为你必须使用
@connect<StateProps, DispatchProps, OwnProps>
来装饰并返回一个接受OwnProps
的类 .如果你看一下TS中的
connect
实现connect<...>
返回一个ComponentDecorator
,当传递组件时(在你的情况下,这是在转发装饰器时透明地完成),无论StateProps
,DispatchProps
返回一个期望OwnProps
的组件 .connect
(非泛型)返回InferableComponentDecorator
它试图根据提供给组件的道具来推断道具,在你的情况下是所有道具的组合(
OwnProps
从上面变成ComponentProps
) .