我正在为我的一个项目构建一个即时消息功能。该项目使用React和Relay。即时消息功能类似于Facebook聊天,您可以在其中查看与之交谈的人员列表,点击某人将打开聊天窗口进行一对一讨论。
在我的实现中,您可以与之聊天的用户列表与已打开的聊天窗口列表分开。因此,用户列表对这个问题实际上并不重要。
关于打开聊天窗口的渲染,我的方法是创建一个父React组件/中继容器。此父组件将跟踪用户打开的聊天窗口,并将构建聊天窗口React组件数组,最后呈现它们。此打开的聊天窗口列表是父React组件中的所有本地状态。
单个聊天窗口React Component / Relay Container有一个片段,用于从参数化字段进行查询,其中参数是聊天窗口讨论所使用的用户的ID。所以,如果这个聊天窗口是与Bob的讨论,那么它将是Bob的id。
考虑到这一切,这是一个示例父组件实现...
class FloatingDiscussionPane extends React.Component {
render() {
return (
<ul>
{this.renderDiscussions()}
</ul>
);
}
renderDiscussions() {
const {teamIds} = this.props;
return teamIds.map(teamId => {
return (
<FloatingDiscussionPaneDiscussion
teamId={teamId} />
);
});
}
};
export default Relay.createContainer(FloatingDiscussionPane, {
fragments: {
session: () => Relay.QL`
fragment on Session {
${/* how to get fragments from the array of discussion windows */}
}
`
}
});
这里是聊天窗口的示例实现......
class FloatingDiscussionPaneDiscussion extends React.Component {
render() {
...
}
};
export default Relay.createContainer(FloatingDiscussionPaneDiscussion, {
fragments: {
session: () => Relay.QL`
fragment on Session {
messages: myDiscussionMessages(team: $teamId) {
...
}
}
`
}
});
如您所见,FloatingDiscussionPaneDiscussion
容器有一个片段,需要包含在父容器FloatingDiscussionPane
中。父组件FloatingDiscussionPane
将具有FloatingDiscussionPaneDiscussion
的数组,但都需要将自己的片段包含在父片段中。
我怎样才能做到这一点?
答案 0 :(得分:0)
我会假设您的架构是团队有消息(复数字段,由GraphQLList
支持),会话有团队。
窗格组件可以加载所有团队及其嵌套消息。
class FloatingDiscussionPane extends React.Component {
render() {
return (
<ul>
{this.renderDiscussions()}
</ul>
);
}
renderDiscussions() {
const {session: {teams}} = this.props;
return teams.map(({id, messages}) => {
return (
<li key={id}>
<FloatingDiscussionPaneDiscussion messages={messages} />
</li>
);
});
}
};
export default Relay.createContainer(FloatingDiscussionPane, {
fragments: {
session: () => Relay.QL`
fragment on Session {
teams {
id
${FloatingDiscussionPaneDiscussion.getFragment('team')}
}
}
`,
},
});
每个窗格都可以使用这些消息并显示它们:
class FloatingDiscussionPaneDiscussion extends React.Component {
render() {
const {team: {messages}} = this.props;
return (
<ul>
{messages.map(({id, text, sender: {name: senderName}}) =>
<li key={id}>{senderName}: {text}</li>
)}
</ul>
);
}
};
export default Relay.createContainer(FloatingDiscussionPaneDiscussion, {
fragments: {
team: () => Relay.QL`
fragment on Team {
messages {
id
recipient { name }
sender { name }
text
}
}
`,
},
});