Reputation: 21
I'm having troubles conditionally calling a mutation from a handler within my main render class. Unfortunately, I am unable to implement a submit button(limitations of project definition, my DOM inputs must dynamically render the new graph onChange) and have to verify conditions before allowing a mutation to execute, yet I seem to be unable to diagnose a fix for this!
Below, you can find the parent component code. Note that the mutation is still within the validation handler, sitting there temporarily until a fix is established.
I've also had a few of the apollo documentation tutorials pointed my way, but unfortunately they rely on a different project structure that I cannot replicate due to project limitations.
Below, you can find the parent component code. Note that the mutation is still within the validation handler, sitting there temporarily until a fix is established.
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>
);
}
}
Upvotes: 1
Views: 2542
Reputation: 1499
There are multiple ways you can call an apollo mutation conditionally because there are multiple ways to call a mutation in general. These ways include the Mutation
component, calling mutate directly on the client, or using the graphql
HOC.
Your example is using the Mutation
component which follows the render prop pattern. In order to use this you need to render the component, and then call the mutation it provides:
...
render() {
return (
<Mutation
mutation={SAVINGS_MUTATION}
variables={{
paymentFrequency: paymentF,
initialDeposit: initialD,
monthlyDeposit: monthlyD,
interestRate: interestR
}}
>
{(savingsmutation, { data }) => {
return (
<CurrencyInput
value={initialDeposit}
onInputChange={() => savingsmutation()}
/>
)
}}
</Mutation>
)
}
...
You could also use the withApollo
HOC to gain access to the client directly and call mutate
on it.
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)
and finally using the 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)
Upvotes: 1