0

I have a simple application where I want to control a counter with React. I am trying to understand how data is sent from the frontend to the backend, and from the backend to the frontend.

I am able to POST the count to the backend, but I cannot return the count back to React. useEffect works for the POST request, but not the GET request and I'm not sure why.

I read this How to send data from React to Flask then back to react and show output on DOM, but I'm not familiar with enough React to understand class components yet.

app.py

from flask import Flask, request

app = Flask(__name__)

@app.route('/led', methods=['GET', 'POST'])
def led():
    count = 1
    if request.method == 'POST':
        count = request.json['count']
        return {'backendCount': count}
    return {'backendCount': count}

LED.js

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

function LED() {

  const [count, setCount] = useState(1)
  const [backendData, setBackendData] = useState([{}]);

  function increment() {
    const newCount = count + 1;
    setCount(newCount);
  }

  function decrement() {
    const newCount = count - 1;
    setCount(newCount);
  }
  
  useEffect(() => {
    fetch('/led').then(
      response => response.json()
    ).then(data => setBackendData(data))
  }, []);

  useEffect(() => {
    fetch('/led', {
        method: 'POST',
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({"count": count})
    }).then(() => {
        console.log("POST: " + count)
    })
  })
  
  return (
    <div className="container">
        <h1>LED Controller</h1>
        <p>Change the number of seconds between the LED turning on and off.</p>
        <h3>{count}</h3>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        <h1>Increment from backend:</h1>
        <h3>{backendData.backendCount}</h3>
    </div>
  );
}

export default LED;
davidism
  • 121,510
  • 29
  • 395
  • 339
Simon1
  • 445
  • 4
  • 12
  • Did you try catching the errors (if there are some..) when fetching data using the `GET` request and log them ? if not, here's an example of how to create a `GET` request with error handling using Fetch API in React: [Fetch API in React](https://reactjs.org/docs/faq-ajax.html) – Alon Barenboim Apr 27 '22 at 01:28
  • There are no errors. The ``GET`` request works on the initial load, but doesn't trigger when I start to increment or decrement the button. I can see the ``POST`` get logged every time I click the button, but nothing happens when I log the ``GET`. – Simon1 Apr 27 '22 at 13:13

2 Answers2

0

I think your useState declaration might be wrong and should define a different variable type.

You should try this, as it appears that backend is an object, and not an array of object.

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

function LED() {

  const [count, setCount] = useState(1)
  const [backendData, setBackendData] = useState({});

  function increment() {
    const newCount = count + 1;
    setCount(newCount);
  }

  function decrement() {
    const newCount = count - 1;
    setCount(newCount);
  }
  
  useEffect(() => {
    fetch('/led').then(
      response => response.json()
    ).then(data => setBackendData(data))
  }, {});

  useEffect(() => {
    fetch('/led', {
        method: 'POST',
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({"count": count})
    }).then(() => {
        console.log("POST: " + count)
    })
  })
  
  return (
    <div className="container">
        <h1>LED Controller</h1>
        <p>Change the number of seconds between the LED turning on and off.</p>
        <h3>{count}</h3>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        <h1>Increment from backend:</h1>
        <h3>{backendData.backendCount}</h3>
    </div>
  );
}

export default LED;
SunPaz
  • 145
  • 7
  • Changing ``[{}]`` to ``{}`` does not work. When I ``console.log(data)``, I can see on the first page reload that the GET request works. The problem is that as the count is incremented, the ``useEffect`` for getting the count from the backend does not work. – Simon1 Apr 27 '22 at 13:03
  • Do you mean that the count always returns the same value? If that's your problem it's totally normal, because you never store "count" value in your backend. It's always initialized with "count = 1" whenever you call your backend. Best practice would be to store your count value in an external repository (database), but you could also defines count outside of your route function. – SunPaz Apr 27 '22 at 20:20
  • Even when I store ``count`` outside of the route, it still doesn't get sent back to the front end whenever I use the increment/decrement buttons, which send a ``POST`` request every time the button is clicked. Ultimately, I've decided to use a button to send ``POST`` and ``GET`` the data. – Simon1 Apr 28 '22 at 01:11
0

I solved my question by using a button to POST the data to the backend and then GET to the frontend.

app.py

from flask import Flask, request

app = Flask(__name__)

class StoredData:
    count = 1
    def update_count(cls, num):
        cls.count = num

data = StoredData()

@app.route('/led', methods=['GET', 'POST'])
def led():
    if request.method == 'POST':
        count = request.json['count']
        data.update_count(count)
        return {'backendCount': data.count}
    return {'backendCount': data.count}

LED.js

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

function LED() {

  const [count, setCount] = useState(1)
  const [backendData, setBackendData] = useState([{}]);

  function increment() {
    const newCount = count + 1;
    setCount(newCount);
  }

  function decrement() {
    const newCount = count - 1;
    setCount(newCount);
  }
  
  function handleTransfer() {
      fetch('/led', {
          method: 'POST',
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({"count": count})
      }).then(() => {
          console.log("POST: " + count)
      })

      fetch('/led').then(
        response => response.json()
      ).then(data => setBackendData(data))
  }
   
  return (
    <div className="container">
        <h1>LED Controller</h1>
        <p>Change the number of seconds between the LED turning on and off.</p>
        <h3>{count}</h3>
        <button onClick={increment}>+</button>
        <button onClick={decrement}>-</button>
        <h1>Increment from backend:</h1>
        <button onClick={handleTransfer}>Transfer Data</button>
        <h3>{backendData.backendCount}</h3>
    </div>
  );
}

export default LED;
Simon1
  • 445
  • 4
  • 12