Skip to content

Instantly share code, notes, and snippets.

@alexhawkins
Created June 29, 2017 20:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexhawkins/30d993ea385ca27fb0d915ea4b32ea2a to your computer and use it in GitHub Desktop.
Save alexhawkins/30d993ea385ca27fb0d915ea4b32ea2a to your computer and use it in GitHub Desktop.
sweet Relay Modern Code for Refetching + Pagination
import React from 'react';
import PropTypes from 'prop-types';
import { graphql } from 'react-relay';
import { createRefetchContainer, QueryRenderer } from 'react-relay';
import { identifyDataKey, hasNextPage, createDataArray } from '../../../utils/RelayHelpers';
const ProductReviewsList = ({ data, loading, containerWidth, role }) => {
const renderRow = () => (
<Flex flexColumn id="ReviewComments">
<Box className="ProductReviews__divider">
<hr />
</Box>
{data.map((productReview) => (
<Box key={productReview.id}>
<ProductReviewComment
{...{
role,
containerWidth,
productReview,
}}
/>
</Box>
))}
</Flex>
);
return (
renderRow()
);
};
ProductReviewsList.defaultProps = {
data: [],
loading: false,
};
ProductReviewsList.propTypes = {
user: PropTypes.object,
containerWidth: PropTypes.number,
data: PropTypes.array,
loading: PropTypes.bool,
};
class ProductReviewsContainer extends Component {
constructor(props) {
super(props);
this.state = {
loading: props.loading,
variables: props.variables,
count: props.variables.first,
};
}
componentWillReceiveProps(nextProps) {
this.setState({
loading: nextProps.loading,
});
}
loadMore = () => {
const { variables, count } = this.state;
const options = {
...variables,
first: variables.first + count,
};
this.setState({
loading: true,
variables: options,
});
this.props.relay.refetch(options, null, () => {
this.setState({
loading: false,
});
});
};
handleScroll = () => {
const { dataKey } = this.props;
const { loading } = this.state;
if (hasNextPage(this.props, dataKey) && !loading) {
this.loadMore();
}
};
render() {
const { dataKey, containerWidth, user } = this.props;
const { loading } = this.state;
const data = createDataArray(this.props, dataKey);
const canLoadMore = data.length > 0 && hasNextPage(this.props, dataKey);
return (
<div>
<ProductReviewsList
data={data}
role={user.role}
loading={loading}
containerWidth={containerWidth}
/>
{canLoadMore &&
<LoadMore
onClick={this.loadMore}
label={loading ? 'Loading...' : 'Load More'}
disabled={loading}
visible={canLoadMore}
/>
}
</div>
);
}
}
ProductReviewsContainer.defaultProps = {
dataKey: null,
loading: false,
variables: {},
};
ProductReviewsContainer.propTypes = {
dataKey: PropTypes.string,
loading: PropTypes.bool,
variables: PropTypes.object,
user: PropTypes.object,
containerWidth: PropTypes.number,
};
const ProductReviewFetch = incomingProps => {
const props = {
...incomingProps,
};
const ProductReviewRefetchContainer = createRefetchContainer(
ProductReviewsContainer,
props.fragments,
props.query,
);
return (
<QueryRenderer
environment={props.environment}
query={props.query}
variables={props.variables}
render={({ props: rendererProps }) => (
<ProductReviewRefetchContainer
variables={props.variables}
loading={rendererProps === null}
dataKey={rendererProps ? identifyDataKey(rendererProps) : null}
{...{ ...rendererProps, ...props }}
/>)
}
/>
);
};
ProductReviewFetch.defaultProps = {
fragments: {},
variables: {},
};
ProductReviewFetch.propTypes = {
environment: PropTypes.object.isRequired,
user: PropTypes.object,
containerWidth: PropTypes.number,
query: PropTypes.func.isRequired,
fragments: PropTypes.object,
variables: PropTypes.object,
};
const ProductReviewsMain = ({ environment, variables, containerWidth, user }) => {
const renderReviews = () => (
<div>
<ProductReviewsRefetch
user={user}
environment={environment}
containerWidth={containerWidth}
variables={{ ...variables, first: variables.first || 3 }}
query={graphql`
query ProductReviewsMainQuery($first: Int!, $name: String!){
viewer {
user {
id
role
productReviews(first: $first, name: $name)
@connection(key: "ProductReviewsMain_productReviews") {
edges {
node {
id
productId
date
rating
comment
canEdit
title
reviewId
firstName
lastName
}
}
pageInfo {
hasNextPage
}
}
}
}
}
`}
/>
</div>
);
return (
renderReviews()
);
};
ProductReviewsMain.propTypes = {
environment: PropTypes.object,
name: PropTypes.string,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment