React TypeScript - 永远不应该导出状态?

问题描述 投票:1回答:2

我有一个React应用程序,它使用方法getInitialInfo异步获取其信息。 MessageView是最重要的组成部分,因此,数据应该处于其状态,即使它不会改变。在一个完美的世界中,IMessageInfo将通过道具。

我们需要export类型IMessageInfo,因为有代码依赖于这个接口。


方案1 - (没有私人国家的扁平解决方案)

import * as React from 'react';
import Message from './Message';

// IMessageInfo needs to be exported because there is code that depends on it
export interface IMessageInfo {
    message: string;
    icon: string;
}

export interface IMessageViewProps {
    getInitialInfo(): Promise<IMessageInfo>;
}

// MessagesView is the upper most Component 
class MessageView extends React.Component<IMessageViewProps, IMessageInfo> {
    constructor(props) {
        super(props);
        this.state = {
            message: '',
            icon: ''
        };
        this.getInitialInfo();
    }

    private async getInitialInfo(): void{
        let info = await this.props.getInitialInfo();
        this.setState(info);
    }

    render(): JSX.Element {
        // Message is reusable component that receives the info through `props`
        return <Message {...this.state} />);
    }
}

从React的设计角度来看,State必须是组件的私有。我同意这一点。但在这里,所有州的信息都是公开的。什么可以抛出这种概念方式。 (例如,如果DATA总是在演示者中管理,为什么在这种情况下它应该是私有的?)


选项2 - (平面解决方案,具有State的私有复制接口)

与一些同事交谈时,他们认为我们应该始终将国家保密。我立即考虑创建一个与IMessageViewState完全相同的IMessageInfo。这样,它在概念上是正确的,但我们会得到一个维护问题(IMessageInfoIMessageViewState在其某些成员更改时更新)。


选项3 - (将IMessageInfo编写为IMessageViewState。具有私有状态)

因此,我的同事建议将IMessageViewState定义为:

interface IMessageViewState {
    messageInfo: IMessageInfo;
}

这样我们就喜欢构图(他们说)。但我认为这里没有任何优势。你看到了吗?例如,如果IMessageInfo的任何成员发生更改(消息或图标),我们需要将所有对象messageInfo传递给this.setState(...),而不是仅更新icon。基本上,这将是一个更容易出错的实现。


选项4 - (扩展IMessageInfo。具有私有状态)

我还想过让IMessageViewState扩展IMessageInfo。这似乎是完成未导出状态的最佳解决方案。但是我的同事说这不是一个好的解决方案,因为我们优先考虑组合。

我认为继承不会带来任何回归。


结论

在我看来,选项1是最适合问题的选项。由于国家所有成员都是公开的,我认为没有必要建立一个私人国家。选项1使代码更清晰。

虽然,如果我选择一个私有州的解决方案,选项4将更适合。

问题:哪种解决方案更正确?

reactjs typescript design-patterns
2个回答
3
投票

我认为这是对interfacestate的一些误解。接口只是某个对象的类型。因此,您可能拥有单独的文件,可以为您解决所有必需的接口。 IMessageInfo可能会在几个地方使用。

State是某种类型的对象。它可以是IMessageInfo或其他类型。 state是一个组件的私有。这是React的design

您可以考虑使用Redux的其他选项,使state成为整个解决方案的核心。在这种情况下,IMessageInfo可以从负责MessageInfo的部分商店导出。

// store/MessageInfo.cs

export interface IMessageInfo { /*...*/ }

const initalMessageInfo: IMessageInfo = { /*...*/ }

export const actionCreators = {
    requestMessageInfo () //...
}

export const reducer: Reducer<IMessageInfo> //...

在这种情况下,你将(1)通过你的解决方案保持IMessageView sigle,(2)根据你的解决方案的几个组件可用的state制作IMessageInfo


1
投票

这样我们就喜欢构图(他们说)。但我认为这里没有任何优势。你看到了吗?例如,如果IMessageInfo的任何成员发生更改(消息或图标),我们需要将所有对象messageInfo传递给this.setState(...),

考虑需要向MessageView内部状态添加更多数据的情况。选项3针对以下情况进行了优化:

interface IMessageViewState {
    messageInfo: IMessageInfo;
}

当它从一开始就以这种方式分离时,很明显你可以在哪里添加你需要添加到私有状态的数据:它被添加到非导出的IMessageViewState,而不会影响导出的IMessageInfo接口的任何用户。

如果你100%确定IMessageInfo拥有MessageView课程所需的一切,你可以选择1。

© www.soinside.com 2019 - 2024. All rights reserved.