【问题标题】:React-apollo v2 - Youshido GraphQlBundle - refetch two queries simultaneouslyReact-apollo v2 - Youshido GraphQlBundle - 同时重新获取两个查询
【发布时间】: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


    【解决方案1】:

    在某些情况下,重新获取功能不是必需的。 感谢@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>
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-20
      • 2018-12-31
      • 2019-05-10
      • 2019-12-13
      • 2021-01-27
      • 2019-11-19
      • 2021-08-02
      • 2021-04-19
      • 2020-12-17
      相关资源
      最近更新 更多