Aar*_*all 18 typescript reactjs redux react-redux
我在弄清楚如何正确键入Redux容器时遇到了一些麻烦.
考虑一个简单的表示组件,可能如下所示:
interface MyProps {
name: string;
selected: boolean;
onSelect: (name: string) => void;
}
class MyComponent extends React.Component<MyProps, {}> { }
Run Code Online (Sandbox Code Playgroud)
从这个组件的角度来看,所有道具都是必需的.
现在我想编写一个容器,将所有这些道具拉出状态:
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);
Run Code Online (Sandbox Code Playgroud)
这是有效的,但是有一个很大的打字问题:映射函数(mapStateToProps
和mapDispatchToProps
)没有保护它们提供正确的数据来实现MyProps
.这容易出错,拼写错误和重构不佳.
我可以使映射函数返回类型MyProps
:
function mapStateToProps(state: MyState): MyProps { }
function mapDispatchToProps(dispatch: IDispatch): MyProps { }
Run Code Online (Sandbox Code Playgroud)
但是这不起作用,除非我使所有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 { }
Run Code Online (Sandbox Code Playgroud)
好吧,这让我更接近我想要的东西,但它有点嘈杂,它让我在容器的形状周围写出我的演示组件道具界面,我不喜欢.
现在又出现了第二个问题.如果我想将容器放在另一个组件中,该怎么办:
<MyContainer />
Run Code Online (Sandbox Code Playgroud)
这使编译错误是name
,selected
和onSelect
无一不缺......但是,由于容器连接到终极版,并提供那些故意的.所以这促使我回到使所有组件道具可选,但我不喜欢它,因为它们不是真正可选的.
当MyContainer
它想要传递一些自己的道具时,事情变得更糟:
<MyContainer section="somethng" />
Run Code Online (Sandbox Code Playgroud)
现在,我想要做的是有section
一个必需的道具MyContainer
,但不是一个道具MyComponent
,和name
,selected
以及onSelect
需要的道具MyComponent
,但可选的,或者没有道具可言MyContainer
.我完全不知道如何表达这一点.
任何指导都将不胜感激!
Rad*_*io- 20
你的最后一个例子是正确的.您还需要定义的是MyOwnProps
接口,并键入该connect
功能.
有了这些类型:https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react-redux/react-redux.d.ts,你可以做这样的事情
interface MyProps {
section: string;
name: string;
selected: boolean;
onSelect: (name: string) => void;
}
interface MyStateProps {
name: string;
selected: boolean;
}
interface MyDispatchProps {
onSelect: (name: string) => void;
}
interface MyOwnProps {
section: string;
}
class MyComponent extends React.Component<MyProps, {}> { }
function mapStateToProps(state: MyState): MyStateProps { }
function mapDispatchToProps(dispatch: IDispatch): MyDispatchProps { }
const MyContainer = connect<MyStateProps, MyDispatchProps, MyOwnProps>(
mapStateToProps,
mapDispatchToProps
)(MyComponent);
Run Code Online (Sandbox Code Playgroud)
这也让你输入ownProps
的mapStateToProps
和mapDispatchToProps
,如
function mapStateToProps(state: MyState, ownProps: MyOwnProps): MyStateProps
Run Code Online (Sandbox Code Playgroud)
只要定义dispatch,state和ownProps类型,就不需要为MyProps类型定义交集类型.这样,您可以将MyProps保留在自己的位置,并让容器或使用组件而没有容器的位置根据需要应用道具.我想这取决于你和你的用例 - 如果你定义MyProps = MyStateProps & MyDispatchProps & MyOwnProps
,它绑定到一个特定的容器,它不太灵活(但不那么冗长).
作为一个解决方案,它非常冗长,但我认为没有办法告诉TypeScript不同的所需道具将在不同的地方组装,并将connect
它们绑在一起.
此外,为了它的价值,我通常选择道具,为了简单起见,所以我没有太多的经验来分享使用这种方法.
归档时间: |
|
查看次数: |
5193 次 |
最近记录: |