Ad

Function Executes Before Component Is Updated

You can find the CodeSandbox here

I am very new to react and I find it a bit confusing to put together my first application given the prevalence of different code styles in react.

The purpose of the application is to execute a GraphQL query with a dynamic query based on form input. On first render it should use data provided in the state. When the user changes the standard value, a new GrapQl should be executed. However, upon trying to change the input value, a new request is released as soon as I press a button and before(!) updating the value.

I have tried different approaches, but none did yield any change.

Here is my code and application

Since my GraphQL server is running locally, you should expect this return:

{
"data": {
    "sensorDataTimeSeriesCurve": [
    {
        "timestamp": "2019-06-12T04:00:00",
        "value": 31.01
    },
    {
        "timestamp": "2019-06-12T05:00:00",
        "value": 33.08
    },
    {
        "timestamp": "2019-06-12T06:00:00",
        "value": 34.28
    }
    ]
}
}

src/index.js

import React, { Component } from "react";
import { render } from "react-dom";

import ApolloClient from "apollo-boost";
import { ApolloProvider, useQuery } from "@apollo/react-hooks";
import gql from "graphql-tag";
import Chart from "./components/charts/chart";

const client = new ApolloClient({
  uri: `https://GRAPHQLENDPOINT`
});

const timeseriesQuery = gql`
  query test0($id1: ID!, $from: DateTime!, $to: DateTime!) {
    sensorDataTimeSeriesCurve(id: $id1, from: $from, to: $to) {
      timestamp
      value
    }
  }
`;

function Timeseries({ id1, from, to }) {
  const { loading, error, data, refetch, networkStatus } = useQuery(
    timeseriesQuery,
    {
      variables: { id1, from, to },
      notifyOnNetworkStatusChange: true
      // pollInterval: 500
    }
  );

  if (networkStatus === 4) return "Refetching!";
  if (loading) return null;
  if (error) return `Error!: ${error}`;
  console.log("Data:", data);

  return (
    <div>
      <Chart data={data.sensorDataTimeSeriesCurve} />
      <button onClick={() => refetch()}>Refetch!</button>
    </div>
  );
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      id1: 20742,
      from: "2019-06-12 03:56:13.567",
      to: "2019-06-22 04:56:13.567"
    };
  }
  handleChange = event => {
    let name = event.target.name;
    let value = event.target.value;
    this.setState({ [name]: value });
  };

  render() {
    return (
      <ApolloProvider client={client}>
        <div>
          <form onSubmit={this.handleSubmit}>
            <label>
              Name:
              <input
                type="text"
                value={this.state.id1}
                onChange={this.handleChange}
              />
            </label>
            <label>
              From:
              <input
                type="text"
                value={this.state.from}
                onChange={this.handleChange}
              />
            </label>
            <label>
              To:
              <input
                type="text"
                value={this.state.to}
                onChange={this.handleChange}
              />
            </label>
            <input type="submit" value="Submit" />
          </form>
          {this.state.id1 && (
            <Timeseries
              id1={this.state.id1}
              from={this.state.from}
              to={this.state.to}
            />
          )}
        </div>
      </ApolloProvider>
    );
  }
}

render(<App />, document.getElementById("root"));

src/components/charts/charts.js

import { LineChart, Line } from "recharts";
import React from "react";

class Chart extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data
    };
  }

  render() {
    return (
      <LineChart width={400} height={400} data={this.state.data}>
        <Line type="monotone" dataKey="value" stroke="#8884d8" />
      </LineChart>
    );
  }
}

export default Chart;

My expected behavior is that a new GraphQL request is made after pressing the submit button.

The actual behavior is that right now, as soon as I attemp to change the input fields, a new request is made with the existing input. It is not possible to change the input values.

Ad

Answer

You query is being sent whenever you render the Timeseries component, and the Timeseries component is being rendered right away (the initial value of you App component is truthy).
Another thing is that you don't seem to give your inputs actual names, so how should they know which value to update?

Ad
source: stackoverflow.com
Ad