React-apollo v2 - Youshido GraphQlBundle - 同时重新获取两个查询

时间:2017-11-21 10:47:40

标签: reactjs pagination graphql symfony-3.3 react-apollo

我正在尝试实施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';

出乎意料的是,当filtersInput被更改时,重新获取功能被称为两次。第一次使用正确的新变量,第二次使用初始变量。因此,客户总数被覆盖

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

返回:带有Symfony3的PHP 7和Youshido\GraphQLBundle

本月我开始做出反应,本月开始做阿波罗。 也许我没有像我应该那样使用重新提取,也许有更好的方法,或者可能有一个错误(我将apollo-client-preset从1.0.2更新到1.0.3而没有看到任何变化)。 也许Youshido方面的解决方案是能够在一个查询中获取客户的列表和客户的数量。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

在某些情况下,不需要重新获取功能。 感谢@stelmakh对此issue !!

的帮助

我的新代码: 孩子:

import React from 'react';
import PropTypes from 'prop-types';
import { compose, graphql } from 'react-apollo';
import { ucfirst } from 'utils/string';

import CustomersTable from 'components/Customer/CustomersTable';
import Typography from 'material-ui/Typography';

import Loading from 'components/Loading/Loading';

import GET_CUSTOMERS_PAGINATED_QUERY from './getCustomersPaginated.graphql';
import GET_CUSTOMERS_PAGINATED_COUNT_QUERY from './getCustomersPaginatedCount.graphql';


const getCustomersPaginatedCountOptions = {
  name: 'customersPaginatedCount',
  options({ variables }) {
    return {
      variables: variables,
      fetchPolicy: 'network-only',
    };
  },
  props({ customersPaginatedCount }) {
    return { customersPaginatedCount: customersPaginatedCount };
  },
};
const getCustomersPaginatedOptions = {
  name: 'customersPaginated',
  options({ variables }) {
    return {
      variables: variables,
      fetchPolicy: 'network-only',
    };
  },
  props({ customersPaginated }) {
    return { customersPaginated: customersPaginated };
  },
};

@compose(
  graphql(GET_CUSTOMERS_PAGINATED_QUERY, getCustomersPaginatedOptions),
  graphql(GET_CUSTOMERS_PAGINATED_COUNT_QUERY, getCustomersPaginatedCountOptions),
)
export default class CustomersTableContainer extends React.PureComponent {

  state = {
    currentOnFilterChangeTimeoutID: null,
  };

  constructor(props) {
    super(props);

    this.onCurrentPageChange = this.onCurrentPageChange.bind(this);
    this.onSortingChange = this.onSortingChange.bind(this);
    this.onFiltersChange = this.onFiltersChange.bind(this);
  }

  onCurrentPageChange(newPage) {
    const { onChange, variables } = this.props;

    onChange({
      currentPage: newPage,
      'offset': newPage * variables.limit,
    });
  }

  onFiltersChange(args) {
    clearTimeout(this.state.currentOnFilterChangeTimeoutID);

    const newCurrentOnFilterChangeTimeoutID = setTimeout(() => {
      const { onChange, variables } = this.props;

      const newVariables = Object.assign({}, variables);

      if (args.length > 0) {
        for ( const i in args ) {
          newVariables['filter' + ucfirst(args[i].columnName)] = args[i].value;
        }
      } else {
        for ( const i in newVariables ) {
          if (i.substr(0, 6) === 'filter') newVariables[i] = null;
        }
      }

      onChange({
        ...newVariables,
        'currentPage': 0,
        'offset': 0 * variables.limit,
      });
    }, 1000);

    this.setState({ currentOnFilterChangeTimeoutID: newCurrentOnFilterChangeTimeoutID });
  }

  render () {
    const { variables, customersPaginated, customersPaginatedCount } = this.props;

    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={variables.currentPage}
            onCurrentPageChange={this.onCurrentPageChange}
            onSortingChange={this.onSortingChange}
            onFiltersChange={this.onFiltersChange}
            pageSize={variables.pageSize}
            totalCount={customersPaginatedCount.customersPaginatedCount || 0}
          />
          {(customersPaginated.loading || customersPaginatedCount.loading) && <Loading />}
        </div>
      </div>
    );
  }

  static propTypes = {
    customersPaginated: PropTypes.object.isRequired,
    customersPaginatedCount: PropTypes.object.isRequired,
    variables: PropTypes.object.isRequired,
    onChange: PropTypes.func.isRequired,
  };
}

家长:

import React from 'react';

import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import AddIcon from 'material-ui-icons/Add';

import CustomersTableContainer from 'containers/Customer/CustomersTableContainer';

export default class CustomersPage extends React.PureComponent {

  constructor(props) {
    super(props);

    this.state = {
      customersTableVariables: {
        filterId: null,
        filterSiren: null,
        filterName: null,
        filterEmail: null,
        pageSize: 10,
        currentPage: 0,
        offset: 0,
        limit: 10,
      },
    };

    this.onCustomersChange = this.onCustomersChange.bind(this);
  }

  onCustomersChange (newVariables) {
    this.setState({
      customersTableVariables: Object.assign({}, this.state.customersTableVariables, newVariables)
    });
  }

  render () {
    const { customersTableVariables } = this.state;
    return (
      <div>
        <Typography align="right">
          <Button fab color="primary" aria-label="add" href="/customer/new">
            <AddIcon />
          </Button>
        </Typography>
        <Typography type="title" gutterBottom>
          Clients/Prospects
        </Typography>
        <CustomersTableContainer variables={customersTableVariables} onChange={this.onCustomersChange} />
      </div>
    );
  }
}