我正在构建一个包含许多不同小部件的仪表板。用户可以添加和删除任何小部件,并以他们喜欢的任何顺序放置它们。每个小部件都有自己的数据需求。构建容器层次结构的正确中继方式是什么?
为了提供一些上下文,这是迄今为止的架构:
Widget
是一个组件,它接受一个配置对象并相应地渲染相应的组件。
class Widget extends React.Component {
render() {
const {widget} = this.props;
// widgetMap is a map that maps string to React component
const ActualWidget = widgetMap.get(widget.component);
return (
<ActualWidget data={widget.data} />
);
}
}
export default Relay.createContainer(Widget, {
fragments: {
data: () => Relay.QL`
fragment on ??? {
# What should be here since we don't know what will be rendered?
}
`
}
});
Dashboard
组件包含用户添加的许多小部件。
class Dashboard extends React.Component {
renderWidgets = () => {
return this.props.widgets.map(widget => {
return <Widget widget={widget}/>;
});
};
render() {
return (
<div>
<span>Hello, {this.props.user.name}</span>
{this.renderWidgets()}
</div>
);
}
}
export default Relay.createContainer(Dashboard, {
fragments: {
// `user` fragment is used by Dashboard
user: () => Relay.QL`
fragment on User {
name
}
`,
// Each widget have different fragment,
// So what should be here?
}
});
更新
我试图让每一个都ActualWidget
成为一个观众的领域。所以架构有点像这样:
type Viewer {
widget1: Widget1
widget2: Widget2
}
type Widget1 {
name,
fieldOnlyForWidget1
}
type Widget2 {
name,
fieldOnlyForWidget2
}
然后对于我的Widget
容器,我尝试动态插入片段。
export default Relay.createContainer(Widget, {
initialVariables: {
component: 'Widget1' // Trying to set the string here
}
fragments: {
data: (variables) => Relay.QL`
fragment on Viewer { # We now know it is Viewer type
# This didn't work because `variables.component` is not string! :(
${widgetMap.get(variables.component).getFragment('viewer')}
}
`
}
});
那是行不通的。我相信 Relay 静态解析了 QL,因此它无法组成动态片段。然而,这只是我的猜测。
我正在测试RootContainer
每个小部件使用的可行性,并将很快更新。