class Comment extends React.Component {
render() {
var {comment} = this.props;
var {author} = comment;
var savePending = this.props.relay.hasOptimisticUpdate(this.props.comment);
return (
{author.name} {comment.text}
{savePending &&

}
);
}
}
Comment = Relay.createContainer(Comment, {
fragments: {
comment: () => Relay.QL`
fragment on Comment {
author { avatar, name }
text
}
`,
},
});
class Story extends React.Component {
_augmentNumCommentsToShow = (delta) => {
this.props.relay.setVariables({
numCommentsToShow: this.props.relay.variables.numCommentsToShow + delta,
});
}
_handleKeyDown = (e) => {
if (e.keyCode === 13 && e.target.value != '') { // enter key
Relay.Store.update(
new AddCommentMutation({
story: this.props.story,
text: e.target.value,
viewer: this.props.viewer,
})
);
this._augmentNumCommentsToShow(1);
e.target.value = '';
}
}
_handleMoreCommentsClick = (e) => {
e.preventDefault();
this._augmentNumCommentsToShow(5);
}
render() {
var {story} = this.props;
var {author, comments} = story;
return (
);
}
}
Story = Relay.createContainer(Story, {
initialVariables: {
numCommentsToShow: 3,
},
fragments: {
story: () => Relay.QL`
fragment on Story {
author { avatar, name }
comments(last: $numCommentsToShow) {
edges {
node {
id
${Comment.getFragment('comment')}
}
}
pageInfo { hasPreviousPage }
}
text
${AddCommentMutation.getFragment('story')}
}
`,
viewer: () => Relay.QL`
fragment on Viewer {
avatar
id
name
${AddCommentMutation.getFragment('viewer')}
}
`,
},
});
class StoriesApp extends React.Component {
_handleLoadMoreClick = () => {
this.props.relay.setVariables({
numStoriesToLoad: this.props.relay.variables.numStoriesToLoad + 3,
});
}
render() {
var {storyFeed} = this.props.viewer;
return (
{storyFeed.edges.map(edge =>
-
)}
{storyFeed.pageInfo.hasNextPage &&
}
);
}
}
StoriesApp = Relay.createContainer(StoriesApp, {
initialVariables: {
numStoriesToLoad: 3,
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
storyFeed(first: $numStoriesToLoad) {
edges {
node {
id
${Story.getFragment('story')},
}
}
pageInfo { hasNextPage }
}
${Story.getFragment('viewer')}
}
`,
}
});
class AddCommentMutation extends Relay.Mutation {
static fragments = {
story: () => Relay.QL`
fragment on Story {
id
}
`,
viewer: () => Relay.QL`
fragment on Viewer {
id
}
`,
};
getCollisionKey() {
return `story-${this.props.story.id}`;
}
getMutation() {
return Relay.QL`mutation{addComment}`;
}
getFatQuery() {
return Relay.QL`
fragment on AddCommentPayload {
commentEdge
story { comments }
}
`;
}
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'story',
parentID: this.props.story.id,
connectionName: 'comments',
edgeName: 'commentEdge',
rangeBehaviors: {
'': 'append',
},
}];
}
getVariables() {
return {
storyId: this.props.story.id,
text: this.props.text,
};
}
getOptimisticResponse() {
return {
commentEdge: {
node: {
author: {
avatar: this.props.viewer.avatar,
id: this.props.viewer.id,
name: this.props.viewer.name,
},
story: {
id: this.props.story.id,
},
text: this.props.text,
},
},
};
}
}
class StoriesRoute extends Relay.Route {
static params = {};
static queries = {
viewer: (Component) => Relay.QL`
query ViewerQuery {
viewer {
${Component.getFragment('viewer')},
}
}
`,
};
static routeName = 'Stories';
}
ReactDOM.render(
,
mountNode
);