Home > Software design >  How to send POST request from React to Flask without submit button
How to send POST request from React to Flask without submit button

Time:04-27

Hey sorry I'm completely new to React and Javascript and I'm really confused about this. I'm trying to create a section where I will have a dropdown list in React. I have already fetched the data from Flask and now when I click my chosen option, I want to send the POST request to Flask (without clicking any submit button).

I was reading different answers and trying to figure it out so I used "fetch" while getting the data and "axios" when trying to send the request.

App.js

import React, { useEffect, useState } from "react"
import { DropdownItem } from "../Components/DropdownItem"
import Select from "react-select"
import axios from "axios"

export const DropdownPage = () => {
    const [years, setYears] = useState([])
    const [selectedYear, setSelectedYear] = useState("")

    useEffect(() => {
        fetch("http://127.0.0.1:5000/api", {
            method: "GET",
            headers: {
                "Content-type": "application/json",
            },
        })
            .then((res) => res.json())
            .then((data) => {
                setYears(data)
            })
    }, [])

    const handleDropdownSelectYear = (e) => {
        setSelectedYear(e.target.value)
    }
    const handleDropdownSubmitYear = (e) => {
        e.preventDefault()
        console.log(e)
        axios
            .post("http://127.0.0.1:5000/api/yearselect", selectedYear)
            .then((res) => {
                console.log(res)
            })
            .catch((err) => {
                console.log(err)
            })
    }
    return (
        <div>
            <form method="post" onSubmit={handleDropdownSubmitYear}>
                <select onChange={handleDropdownSelectYear}>
                    <option value="">Select Year</option>
                    {years.map((year) => (
                        <DropdownItem key={year.id} year={year}></DropdownItem>
                    ))}
                </select>
            </form>
        </div>
    )
}

api.py

class Year(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.Text, nullable=False)

    def __str__(self):
        return f'{self.id} {self.content}'


def year_serializer(year):
    return {'id': year.id,
            'content': year.content}


@app.route('/api', methods=['GET'])
def index():
    return jsonify([*map(year_serializer, Year.query.all())])


@app.route('/api/yearselect', methods=['POST'])
def yearselect():
    if request.method == 'POST':
        request_data = request.get_json(force=True)
        year = Year(content=request_data['content'])
        db.session.add(year)
        db.session.commit()
        return {"201": request_data['content']}

If there's any other information/code you need, please let me know. Also, I'm planning to recreate this image below. So, when I make my selection on the first dropdown, it should send a request to flask and narrow down the options for the next dropdown and so on. Let me know if you need any clarification. Thanks!! enter image description here

CodePudding user response:

If you want to send the POST request when a selection is made, you don't need a <form> or a submit handler.

Instead, add an effect hook that listens for changes to selectedYear

// if selectedYear is going to be an object, don't initialise it as a string
const [selectedYear, setSelectedYear] = useState();

useEffect(() => {
  if (selectedYear) {
    fetch("http://127.0.0.1:5000/api/yearselect", {
      method: "POST",
      body: JSON.stringify(selectedYear),
      headers: { "content-type": "application/json" },
    })
      .then((res) => {
        if (!res.ok) return Promise.reject(res);
        return res.json();
      })
      .then((data) => {
        // do something with data ¯\_(ツ)_/¯
      })
      .catch(console.error);
  }
}, [selectedYear]); // effect hook dependencies

Effect hooks also run when the value is initialised so checking the value of selectedYear before making the request is advisable.


The Axios equivalent would be

axios.post("http://127.0.0.1:5000/api/yearselect", selectedYear)
  .then(({ data }) => {
    // do something with data
  })
  .catch(err => {
    console.error(err.toJSON());
  });
  • Related