Home > Net >  React Unable To Receive Data From Flask
React Unable To Receive Data From Flask

Time:04-14

I am trying to send form data from React front end to Flask back end. The Flask back end will then query a database and return the queried data back to Flask. Flask will then graph the data. I know that my first two parts work correctly (I am able to send the React form input to Flask and Flask is able to complete a query). However, my React can't seem to retrieve the information that Flask is sending in the /data route after i press the submit button in react. I am trying to use a listener in React to fetch the Flask json data at every 5 seconds. I want React to fetch the data after I press submit.


import React, { useState, Component, useEffect } from "react";


export const DateForm = () => {
    const handleSubmit = (event) => {
        event.preventDefault();
        console.log("handleSubmit Runs");


        const input = {
            "startDate": startDate, "endDate": endDate
        };

        fetch("/acceptDates", {
            method: 'POST',
            body: JSON.stringify(input),
            headers: {
                'Content-Type': 'application/json'
            }
        }).then(res => res.json())
            .then(console.log("WORKED"))
            .catch(error => console.error('Error:', error));


    };

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <label> Enter Dates:</label>
                <br></br>
                <input type="text" id="startDate" name="startDate" />
                <br></br>
                <input type="text" id="endDate" name="endDate" />
                <br></br>
                <input type="submit" value="submit" />
            </form>
        </div>
    );

}


app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'


@app.after_request
def set_headers(response):
    response.headers["Access-Control-Allow-Origin"] = "*"
    response.headers["Access-Control-Allow-Headers"] = "*"
    response.headers["Access-Control-Allow-Methods"] = "*"
    return response

# gets the input dates from the React form and sends them to /data to get the data
@app.route('/acceptDates', methods=['GET', 'POST'])
def get_dates():

    sent_dates = request.get_json()

    if sent_dates is not None:

        @copy_current_request_context
        def interval():

           
            sd = sent_dates['startDate']
            data = retrieve_data(sd)
            threading.Timer(1, interval).start()
            return ({"dates": data[0], "open_price": data[1]})

        print("SENDING DATA")
        return interval()

    return {"dates": [], "open_price": []}


import React, { useState, Component, useEffect } from "react";
import Plot from 'react-plotly.js';


export const Chart = () => {

    const [testData, setTestData] = useState([{}])

    useEffect(() => {
        const intervalId = setInterval(() => {  //assign interval to a variable to clear it.

            fetch("/acceptDates").then(
                res => res.json()).then(
                    testData => {
                        console.log(testData)
                        if (testData['dates'].length != 3) {
                            setTestData(testData)
                            console.log(testData)
                        }

                    })

        }, 1000)

        return () => clearInterval(intervalId); 

    }, [useState])

    return (
        <div>
            <Plot
                data={[
                    {
                        x: testData['dates'],//[1, 2, 3],
                        y: testData['open_price'], //[1, 2, 3],
                        type: 'scatter'
                    }
                ]}
                layout={{ width: 1000, height: 500, title: 'Google Stock Data' }}
            />
        </div>
    )
}

CodePudding user response:

When creating an interval in a React component, it should be done in a useEffect hook since you only want to create it once when the component is instantiated.

useEffect(() => {
  const intervalId = setInterval(function () {
      fetch("/data").then(
          res => res.json()).then(
              data => {
                  setData(data)
                  console.log(data)
              })
  }, 5000);

  // clear the interval when component unmounts
  return () => clearInterval(intervalId);
}, []);

CodePudding user response:

In your backend, use a global variable to update the sent in query.


@app.route('/acceptDates', methods=['GET', 'POST'])
def get_dates():

    global startD


    sent_dates = request.get_json()
    if sent_dates is not None:
        startD = sent_dates['startDate']

        return "DONE"
    else:

        return "BAD INPUT"

@app.route('/data', methods=['GET', 'POST'])
def get_data():

    data = retrieve_data(startD)

    return jsonify({"dates": data[0], "open_price": data[1]})


if __name__ == '__main__':
    global startD
    # default date
    startD = "2019-12-18"
    app.run(debug=True)

  • Related