gpt4 book ai didi

reactjs - TypeScript 与 Redux 容器斗争

转载 作者:搜寻专家 更新时间:2023-10-30 20:31:27 27 4
gpt4 key购买 nike

我在弄清楚如何正确输入 Redux containers 时遇到了一些问题.

考虑一个可能如下所示的简单展示组件:

interface MyProps {
name: string;
selected: boolean;
onSelect: (name: string) => void;
}
class MyComponent extends React.Component<MyProps, {}> { }

从这个组件的角度来看,所有的 Prop 都是必需的。

现在我想编写一个容器,将所有这些 Prop 拉出状态:

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);

这行得通,但是有一个很大的类型问题:映射函数(mapStateToPropsmapDispatchToProps)没有保护它们提供正确的数据来实现 我的 Prop 。这很容易出现错误、拼写错误和重构不佳。

我可以让映射函数返回类型MyProps:

function mapStateToProps(state: MyState): MyProps { }

function mapDispatchToProps(dispatch: IDispatch): MyProps { }

但是这不起作用,除非我将所有 MyProp 属性设为可选,这样每个映射函数都可以只返回它们关心的部分。我不想让 Prop 成为可选的,因为它们对于展示组件来说不是可选的。

另一种选择是为每个 map 功能拆分 Prop ,并将它们组合为组件 Prop :

// 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 { }

好吧,这让我更接近我想要的东西,但它有点吵,它让我围绕容器的形状编写我的展示组件 prop 界面,我不喜欢这样。

现在第二个问题出现了。如果我想将容器放在另一个组件中怎么办:

<MyContainer />

这给出了 nameselectedonSelect 都丢失的编译错误...但这是故意的,因为容器正在连接到Redux 并提供这些。所以这让我回到了让所有组件 Prop 都可选的状态,但我不喜欢那样,因为它们并不是真正可选的。

MyContainer 有一些它自己想要传入的 props 时,情况会变得更糟:

<MyContainer section="somethng" />

现在我要做的是让 section 成为 MyContainer 的必需 Prop ,但不是 MyComponent 的 Prop ,并且 nameselectedonSelectMyComponent 的必需属性,但 MyContainer< 的可选属性或根本不是属性。我完全不知该如何表达。

如有任何指导,我们将不胜感激!

最佳答案

您在上一个示例中走在了正确的轨道上。您还需要定义一个MyOwnProps 接口(interface),并键入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);

这还允许您在 mapStateToPropsmapDispatchToProps 中键入 ownProps,例如

function mapStateToProps(state: MyState, ownProps: MyOwnProps): MyStateProps

只要定义了 dispatch、state 和 ownProps 类型,就不需要为 MyProps 类型定义交集类型。这样,您可以将 MyProps 保留在自己的位置,并让容器或在没有容器的情况下使用组件的地方根据需要应用 Prop 。我想这取决于您和您的用例 - 如果您定义 MyProps = MyStateProps & MyDispatchProps & MyOwnProps,它会绑定(bind)到一个特定的容器,该容器不太灵活(但不那么冗长)。

作为解决方案,它非常冗长,但我不认为有任何方法可以绕过告诉 TypeScript 所需 Prop 的不同部分将在不同的地方组装,connect 将把它们绑在一起。

此外,尽管如此,为了简单起见,我通常使用可选 Prop ,所以我没有太多使用这种方法的经验可以分享。

关于reactjs - TypeScript 与 Redux 容器斗争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40671978/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com