希望有条件地调用突变

Looking to conditionally call a mutation

我在有条件地从主渲染中的处理程序调用突变时遇到问题 class。不幸的是,我无法实现提交按钮(项目定义的限制,我的 DOM 输入必须动态呈现新图形 onChange)并且必须在允许执行突变之前验证条件,但我似乎无法诊断修复此问题!

在下面,您可以找到父组件代码。请注意,突变仍在验证处理程序中,暂时坐在那里直到建立修复。

我也有一些 apollo 文档教程指出了我的方向,但不幸的是它们依赖于不同的项目结构,由于项目限制我无法复制。

在下面,您可以找到父组件代码。请注意,突变仍在验证处理程序中,暂时坐在那里直到建立修复。

import React, { Component } from "react";
import CurrencyInput from "./CurrencyInput";
import SliderInput from "./SliderInput";
import DisplayGraph from "./DisplayGraph";
import "./InputGraphSection.css";
import FrequencyInput from "./FrequencyInput";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const SAVINGS_MUTATION = gql`
    mutation savingsmutation(
        $paymentFrequency: Int!
        $initialDeposit: Float!
        $monthlyDeposit: Float!
        $interestRate: Float!
    ) {
        createSavings(
            paymentFrequency: $paymentFrequency
            initialDeposit: $initialDeposit
            monthlyDeposit: $monthlyDeposit
            interestRate: $interestRate
        ) {
            savings {
                months {
                    id
                    totalInterest
                    totalValue
                }
            }
        }
    }
`;

export default class InputGraphSectionContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            savT: [{ x: 0, y: 0 }],
            intT: [{ x: 0, y: 0 }]
        };
    }
    handleComplete = ({ data: { createSavings } }) => {
        this.setState(prevState => ({
            savT: [
                ...prevState.savT,
                // month is inside the data returned by the API????
                { x: createSavings.savings.months.id, y: createSavings.savings.months.totalValue }
            ],
            intT: [
                ...prevState.intT,
                { x: createSavings.savings.months.id, y: createSavings.savings.months.totalInterest }
            ]
        }));
    };
    render() {
        const { savT, intT } = this.state;
        return (
            <Mutation mutation={SAVINGS_MUTATION} onCompleted={this.handleComplete}>
                {savingsmutation => (
                    <InputGraphSection mutate={savingsmutation} savT={savT} intT={intT} />
                )}
            </Mutation>
        );
    }
}

class InputGraphSection extends Component {
    constructor(props) {
        super(props);
        this.state = {
            initialDeposit: "",
            monthlyDeposit: "",
            interestRate: 0,
            paymentFrequency: ""
        };
    }
    componentDidUpdate({ mutate }, prevState) {
        console.log(this.state);

        if (
            this.state.initialDeposit !== "" &&
            this.state.monthlyDeposit !== "" &&
            this.state.paymentFrequency !== "" &&
            prevState !== this.state
        ) {
            //If currencyInput elements are returning strings, convert to ints here.
            var paymentF = Number(this.state.paymentFrequency);
            var initialD = parseFloat(this.state.initialDeposit);
            var monthlyD = parseFloat(this.state.monthlyDeposit);
            var interestR = parseFloat(this.state.interestRate)/100;

            console.log("execute mutation");
            mutate({
                variables: {
                    paymentFrequency: paymentF,
                    initialDeposit: initialD,
                    monthlyDeposit: monthlyD,
                    interestRate: interestR
                }
            });
            console.log("Mutation query commencing")
        } else {
            console.log("Input Requirements not met, will not generate graph.");
        }
    }
    handleChange = evt => {
        const { name, value } = evt.target;
        this.setState({ [name]: value });
    };

    render() {
        const {
            initialDeposit,
            monthlyDeposit,
            interestRate,
            paymentFrequency
        } = this.state;
        const { savT, intT } = this.props;
        return (
            <div>
                <p className="input-label">
                    Inputs must be positive and have no more than 15 digits with 2 decimal
                    places!
                </p>
                <div className="financial-inputs">
                    <p className="input-label">What is your initial Deposit?</p>
                    <CurrencyInput
                        name="initialDeposit"
                        value={initialDeposit}
                        onInputChange={this.handleChange}
                    />
                    <p className="input-label">How much will you save each month?</p>
                    <CurrencyInput
                        name="monthlyDeposit"
                        value={monthlyDeposit}
                        onInputChange={this.handleChange}
                    />
                    <p className="input-label">
                        What is the annual interest rate you have acquired?
                    </p>
                    <SliderInput
                        name="interestRate"
                        value={Number(interestRate)}
                        onInputChange={this.handleChange}
                    />
                    <p className="input-label">
                        Specify the frequency of interest compounding.
                    </p>
                    <FrequencyInput
                        name="paymentFrequency"
                        value={paymentFrequency}
                        onInputChange={this.handleChange}
                    />
                </div>
                <div className="financial-display">
                    <DisplayGraph savT={savT} intT={intT} />
                </div>
            </div>
        );
    }
}

有多种方法可以有条件地调用 apollo 突变,因为通常有多种方法可以调用突变。这些方式包括 Mutation 组件,直接在客户端调用 mutate,或者使用 graphql HOC。

您的示例使用的是 Mutation component,它遵循 render prop 模式。为了使用这个你需要渲染组件,然后调用它提供的突变:

...
render() {
  return (
    <Mutation
      mutation={SAVINGS_MUTATION}
      variables={{
        paymentFrequency: paymentF,
        initialDeposit: initialD,
        monthlyDeposit: monthlyD,
        interestRate: interestR
      }}
    >
      {(savingsmutation, { data }) => {
        return (
          <CurrencyInput
            value={initialDeposit}
            onInputChange={() => savingsmutation()}
          />
        )
      }}
    </Mutation>
  )
}
...

您也可以使用 withApollo HOC 直接访问客户端并在其上调用 mutate

import { withApollo } from 'react-apollo'

class InputGraphSection extends Component {
  handleChange() {
    this.props.client.mutate({
      mutation: SAVINGS_MUTATION,
      variables: {
        paymentFrequency: paymentF,
        initialDeposit: initialD,
        monthlyDeposit: monthlyD,
        interestRate: interestR
      }
    })
  }
}

export default withApollo(InputGraphSection)

最后使用 graphql HOC

import { graphql } from 'react-apollo'

class InputGraphSection extends Component {
  handleChange() {
    this.props.mutate({
      paymentFrequency: paymentF,
      initialDeposit: initialD,
      monthlyDeposit: monthlyD,
      interestRate: interestR
    })
  }
}

export default graphql(SAVINGS_MUTATION)(InputGraphSection)