React TypeScript-永远不要导出状态?

时间:2019-04-30 02:08:24

标签: reactjs typescript design-patterns

我有一个React App,它使用getInitialInfo方法异步获取其 info 信息。 MessageView是最重要的组件,因此 Data 应该保持其状态,即使它不会改变也是如此。在理想情况下,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(...),而不是仅更新{{1} } 例如。基本上,这将是一个更容易出错的实现。


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

我还考虑过将icon扩展为IMessageViewState。看来完成未导出状态的最佳解决方案。 但是我的同事说这不是一个好的解决方案,因为我们将继承优先于组合。

我认为继承不会带来任何麻烦。


结论

我认为,选项1 是最适合该问题的选项。由于该州的所有成员国都是公开的,所以我认为没有必要建立一个私人国家。 选项1 使代码更整洁。

尽管,如果我选择私有国家的解决方案,则选项4 会更好。

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

2 个答案:

答案 0 :(得分: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保留在解决方案中,(2)使基于state的{​​{1}}可用于解决方案的多个组件。

答案 1 :(得分:1)

  

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

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

interface IMessageViewState {
    messageInfo: IMessageInfo;
}

以这种方式从一开始就将其分隔开时,很明显,您可以在其中添加需要添加到私有状态的任何数据:将其添加到未导出的IMessageViewState,而不会影响已导出的{{ 1}}界面。

如果您100%确定IMessageInfo具有IMessageInfo类所需的一切,则可以选择选项1。