我有一个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
。这样,它在概念上是正确的,但我们会遇到维护问题(IMessageInfo
和IMessageViewState
会在其某些成员发生更改时进行更新)。
选项3 -(将IMessageInfo组合为IMessageViewState。具有私有状态)
因此,我的同事建议将IMessageViewState
定义为:
interface IMessageViewState {
messageInfo: IMessageInfo;
}
这样,我们支持组成(他们说)。但我认为在这里进行构图没有任何好处。你看到了吗?例如,如果IMessageInfo
的任何成员发生了更改(消息或图标),我们将需要将所有对象messageInfo
传递给this.setState(...)
,而不是仅更新{{1} } 例如。基本上,这将是一个更容易出错的实现。
选项4 -(扩展了IMessageInfo。具有私有状态)
我还考虑过将icon
扩展为IMessageViewState
。看来完成未导出状态的最佳解决方案。
但是我的同事说这不是一个好的解决方案,因为我们将继承优先于组合。
我认为继承不会带来任何麻烦。
结论
我认为,选项1 是最适合该问题的选项。由于该州的所有成员国都是公开的,所以我认为没有必要建立一个私人国家。 选项1 使代码更整洁。
尽管,如果我选择私有国家的解决方案,则选项4 会更好。
问题:哪种解决方案更正确?
答案 0 :(得分:3)
我认为这是对interface
和state
的一些误解。接口只是某些对象的类型。因此,您可能拥有单独的文件,该文件可以导出解决方案的所有必需接口。 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。