2017-11-21 1 views
0

Ich versuche Apollo zu implementieren, um die Tabellenkomponente meines Kunden zu füttern.React-apollo v2 - Youshido GraphQlBundle - wiederhole zwei Abfragen gleichzeitig

import CustomersTable from 'components/Customer/CustomersTable'; 

Diese Tabelle muss filterbar, sortierbar und paginiert sein. Ich habe 200.000 Kunden in der MySQL-Tabelle. Deshalb werden Filter, Sortierungen und Paginierung serverseitig berechnet. Ich muss separat Kunden Gesamtanzahl für Paginierung und die Kundenliste abfragen.

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

unerwartet, wenn die filtersInput geändert wird die Refetch Funktion zweimal genannt. Das erste Mal mit den korrekten neuen Variablen und das zweite Mal mit Anfangsvariablen. So ist die Gesamtzahl der Kunden überschrieben.

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, 
    }; 
    }, 
}; 

Diese beiden Abfragen zusammengesetzt sind als here Tipps (für keine Fehler):

@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, 
    }; 
} 

Meine Konsole anmeldet Bauteilbelastung in einem erwarteten Verhalten:

{variables: {filterId: null, filterSiren: null, filterName: null, filterEmail: null}, operationName: "getCustomersPaginatedCount" 
{variables: {filterId: null, filterSiren: null, filterName: null, filterEmail: null}, operationName: "getCustomersPaginated" 

Meine Konsole anmeldet eine Filtereingangsänderung in einem unerwarteten Verhalten:

{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, 
) 
} 

Mein environnement:

Vorder: reactjs mit reagieren-apollo

Zurück: PHP 7 mit Symfony3 und Youshido\GraphQLBundle

reagiere ich in diesem Jahr begonnen und in diesem Monat apollo. Vielleicht benutze ich Refetch nicht wie ich sollte, vielleicht gibt es einen besseren Weg, oder vielleicht gibt es einen Bug (Ich aktualisierte apollo-client-preset von 1.0.2 auf 1.0.3 ohne Änderungen zu sehen). Vielleicht gibt es eine Lösung auf Youshidos Seite, um die Kundenliste und die Kundenanzahl in einer Abfrage abzurufen.

Danke für Ihre Hilfe.

Antwort

0

In einigen Situationen ist die Refetch-Funktion nicht erforderlich. Dank @stelmakh für seine Hilfe zu diesem issue !!

Mein neuer Code: Child:

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, 
    }; 
} 

Parent:

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> 
    ); 
    } 
} 
Verwandte Themen