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)