【发布时间】:2017-04-02 00:04:56
【问题描述】:
我在弄清楚如何正确输入 Redux containers 时遇到了一些麻烦。
考虑一个可能如下所示的简单展示组件:
interface MyProps {
name: string;
selected: boolean;
onSelect: (name: string) => void;
}
class MyComponent extends React.Component<MyProps, {}> { }
从这个组件的角度来看,所有的道具都是必需的。
现在我想编写一个容器,将所有这些道具拉出状态:
function mapStateToProps(state: MyState) {
return {
name: state.my.name,
selected: state.my.selected
};
}
function mapDispatchToProps(dispatch: IDispatch) {
return {
onSelect(name: string) {
dispatch(mySelectAction(name));
}
};
}
const MyContainer = connect(
mapStateToProps,
mapDispatchToProps
)(MyComponent);
这可行,但有一个大的打字问题:映射函数(mapStateToProps 和mapDispatchToProps)没有保护它们提供正确的数据来满足MyProps。这很容易出现错误、拼写错误和糟糕的重构。
我可以让映射函数返回类型MyProps:
function mapStateToProps(state: MyState): MyProps { }
function mapDispatchToProps(dispatch: IDispatch): MyProps { }
但是,除非我将所有 MyProp 属性设为可选,否则这不起作用,以便每个映射函数只能返回他们关心的部分。我不想让道具成为可选的,因为它们对于展示组件来说不是可选的。
另一种选择是拆分每个地图功能的道具并将它们组合为组件道具:
// MyComponent
interface MyStateProps {
name: string;
selected: boolean;
}
interface MyDispatchProps {
onSelect: (name: string) => void;
}
type MyProps = MyStateProps & MyDispatchProps;
class MyComponent extends React.Component<MyProps, {}> { }
// MyContainer
function mapStateToProps(state: MyState): MyStateProps { }
function mapDispatchToProps(dispatch: IDispatch): MyDispatchProps { }
好的,这让我更接近我想要的,但它有点吵,它让我围绕容器的形状编写我的演示组件道具界面,我不喜欢。
现在出现了第二个问题。如果我想将容器放在另一个组件中怎么办:
<MyContainer />
这会产生 name、selected 和 onSelect 都丢失的编译错误...但这是故意的,因为容器正在连接到 Redux 并提供这些错误。所以这促使我回到让所有组件道具成为可选的,但我不喜欢这样,因为它们并不是真正的可选。
当MyContainer 有一些自己想要传递的道具时,事情会变得更糟:
<MyContainer section="somethng" />
现在我要做的是让section 是MyContainer 的必需道具,但不是MyComponent 的道具,而name、selected 和onSelect 是@ 的必需道具987654343@ 但可选或根本不是 MyContainer 的道具。我完全不知道该怎么表达。
对此的任何指导将不胜感激!
【问题讨论】:
标签: reactjs typescript redux react-redux