【发布时间】:2018-05-04 19:18:12
【问题描述】:
我正在尝试实施 apollo 来提供我客户的表格组件。
import CustomersTable from 'components/Customer/CustomersTable';
此表必须是可过滤、可排序和分页的。我在 MySQL 表中有 200.000 个客户。这就是过滤器、排序和分页在服务器端计算的原因。我需要单独查询分页的客户总数和客户列表。
import GET_CUSTOMERS_PAGINATED_QUERY from './getCustomersPaginated.graphql';
import GET_CUSTOMERS_PAGINATED_COUNT_QUERY from './getCustomersPaginatedCount.graphql';
出乎意料的是,当过滤器输入发生变化时,重新获取函数被调用两次。第一次使用正确的新变量,第二次使用初始变量。所以客户总数被覆盖。
const initialFilters = {
filterId: null,
filterSiren: null,
filterName: null,
filterEmail: null,
};
const getCustomersPaginatedCountOptions = {
name: 'customersPaginatedCount',
options() {
return {
variables: {
...initialFilters,
},
fetchPolicy: 'network-only',
};
},
props({ customersPaginatedCount }) {
return {
customersPaginatedCount: customersPaginatedCount,
};
},
};
const getCustomersPaginatedOptions = {
name: 'customersPaginated',
options({ offset, limit }) {
return {
variables: {
offset: offset,
limit: limit,
...initialFilters,
},
fetchPolicy: 'network-only',
};
},
props({ customersPaginated }) {
return {
customersPaginated: customersPaginated,
};
},
};
这两个查询组成为通知here(没有错误):
@compose(
graphql(GET_CUSTOMERS_PAGINATED_QUERY, getCustomersPaginatedOptions),
graphql(GET_CUSTOMERS_PAGINATED_COUNT_QUERY, getCustomersPaginatedCountOptions),
)
export default class CustomersTableContainer extends React.PureComponent {
state = {
offset: this.props.offset,
limit: this.props.limit,
pageSize: 10,
currentPage: 0,
filters: initialFilters,
currentOnFilterChangeTimeoutID: null,
};
constructor(props) {
super(props);
this.onCurrentPageChange = this.onCurrentPageChange.bind(this);
this.onFiltersChange = this.onFiltersChange.bind(this);
}
onCurrentPageChange(newPage) {
const { customersPaginated } = this.props;
const { limit, filters } = this.state;
customersPaginated.refetch({
offset: newPage * limit,
...filters,
});
this.setState({ currentPage: newPage });
}
onFiltersChange(args) {
const { customersPaginated, customersPaginatedCount } = this.props;
const { limit } = this.state;
const newFilters = Object.assign({}, initialFilters);
for ( const i in args ) {
newFilters['filter' + ucfirst(args[i].columnName)] = args[i].value;
}
customersPaginated.refetch({
offset: 0 * limit,
...newFilters,
});
// --- >> THE REFETCH FUNCTION IS TRIGGERED TWICE HERE ! << ---
customersPaginatedCount.refetch({
...newFilters,
});
// here 'test' is displayed once, so onFiltersChange is called once too as expected
console.log('test');
this.setState({
currentPage: 0,
filters: newFilters,
});
}
render () {
const { customersPaginated, customersPaginatedCount } = this.props;
const { currentPage, pageSize } = this.state;
if (customersPaginated.error) console.error( customersPaginated.error );
if (customersPaginatedCount.error) console.error( customersPaginatedCount.error );
return (
<div>
{(customersPaginated.error || customersPaginatedCount.error) && (
<Typography color="error" gutterBottom>
Une erreur est survenue.
</Typography>
)}
<div>
<CustomersTable
customers={customersPaginated.customersPaginated}
currentPage={currentPage}
onCurrentPageChange={this.onCurrentPageChange}
onFiltersChange={this.onFiltersChange}
pageSize={pageSize}
totalCount={customersPaginatedCount.customersPaginatedCount || 0}
/>
{(customersPaginated.loading || customersPaginatedCount.loading) && <Loading />}
</div>
</div>
);
}
static propTypes = {
customersPaginated: PropTypes.object.isRequired,
customersPaginatedCount: PropTypes.object.isRequired,
offset: PropTypes.number.isRequired,
limit: PropTypes.number.isRequired,
};
}
我的控制台以预期的行为记录组件加载:
{variables: {filterId: null, filterSiren: null, filterName: null, filterEmail: null}, operationName: "getCustomersPaginatedCount"
{variables: {filterId: null, filterSiren: null, filterName: null, filterEmail: null}, operationName: "getCustomersPaginated"
我的控制台以意外行为记录过滤器输入更改:
{variables: {filterId: null, filterSiren: null, filterName: "example of customer name", filterEmail: null}, operationName: "getCustomersPaginated"
{variables: {filterId: null, filterSiren: null, filterName: "example of customer name", filterEmail: null}, operationName: "getCustomersPaginatedCount"
{variables: {filterId: null, filterSiren: null, filterName: null, filterEmail: null}, operationName: "getCustomersPaginatedCount"
getCustomersPaginated.graphql:
query getCustomersPaginated(
$filterId: Int,
$filterSiren: String,
$filterName: String,
$filterEmail: String,
$offset: Int,
$limit: Int
) {
customersPaginated(
filterId: $filterId,
filterSiren: $filterSiren,
filterName: $filterName,
filterEmail: $filterEmail,
offset: $offset,
limit: $limit
) {
id
name
siren
email
activity {
id
name
shortName
code
}
salesFollower {
id
username
firstname
lastname
email
initials
enabled
}
customerGroup {
id
name
code
enabled
}
coreBusiness {
id
name
codeApe
codeNaf
}
}
}
getCustomersPaginatedCount.graphql:
query getCustomersPaginatedCount(
$filterId: Int,
$filterSiren: String,
$filterName: String,
$filterEmail: String
) {
customersPaginatedCount(
filterId: $filterId,
filterSiren: $filterSiren,
filterName: $filterName,
filterEmail: $filterEmail,
)
}
我的环境:
前面 : reactjs 和 react-apollo
返回:PHP 7 与 Symfony3 和 Youshido\GraphQLBundle
我今年开始做出反应,本月开始阿波罗。 也许我没有像我应该的那样使用 refetch,也许有更好的方法,或者可能有一个错误(我将 apollo-client-preset 从 1.0.2 更新到 1.0.3 没有看到任何变化)。 也许Yoshido那边有一个解决方案,能够在一次查询中获取客户列表和客户数量。
感谢您的帮助。
【问题讨论】:
标签: reactjs pagination graphql symfony-3.3 react-apollo