user3468921
user3468921

Reputation: 601

React - not refresh page after post with error response

I have application, which fetches data from the server, which is written in nodeJS. Using componentDidMount i fetch the data. On page is input for name a table with data and every row has checkbox. When I click on button 'send', selected rows are send on backend. On backend I validate unique name. If is not, I return error. But fronted is every time refreshed. And is not possible get error message.

import React, {Component} from 'react';
import axios from 'axios';
import MyNavbar from "./MyNavbar";

class Offer extends Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleCheckedOrder = this.handleCheckedOrder.bind(this);
        this.state = {
            offers: [],
            name: '',
            selectedFoods: [],
            selectedBuild: 'Nevybráno',
            isOrderChecked: false
        };
    }

    componentDidMount() {
        this.getOffer();
    }

    getOffer() {
        const url = '/offer';
        axios.get(url).then(response => {
            this.setState({offers: response.data})
        }).catch(() => 'Cannot load menu');
    };

    handleNameChange = evt => {
        this.setState({name: evt.target.value});
    };

    handleChecboxChange = offer => {
        if (this.state.selectedFoods.includes(offer)) {
            this.setState({selectedFoods: this.state.selectedFoods.filter(item => item !== offer)});
        } else {
            this.setState({selectedFoods: [...this.state.selectedFoods, offer]});
        }
    };

    handleCheckedOrder() {
        this.setState({isChecked: !this.state.isChecked});
    }

    isValid() {
        let isEnabledSubmit = this.state.name.length > 0;
        let isSelectedFoodAndNotOnlySoap = this.state.selectedFoods.length > 0 && this.state.selectedFoods.some(food => food.index !== 0);
        let isSelectedBuild = this.state.selectedBuild !== 'Nevybráno';
        return isEnabledSubmit && isSelectedFoodAndNotOnlySoap && isSelectedBuild;
    }

    handleSubmit() {
        axios({
            method: 'post',
            url: '/order',
            headers: {},
            data: {
                name: this.state.name,
                food: this.state.selectedFoods,
                order: this.state.isChecked,
                build: this.state.selectedBuild
            }
        });
    };

    render() {
        const {offers} = this.state;
        const options = ["Nevybráno", "A", "B"];

        return (
            <div>
                <MyNavbar/>
                <div className="container">
                    <form className="form-inline justify-content-center" onSubmit={this.handleSubmit}>
                        <table className="table">
                            <tbody>
                            <tr>
                                <th>&nbsp;</th>
                                <th>#</th>
                                <th>Váha</th>
                                <th>Menu</th>
                                <th>Cena</th>
                            </tr>
                            {offers.map((offer) => {
                                return (
                                    <tr key={offer.index}>
                                        <td style={{width: '5%'}}>
                                            <input type="checkbox" className="checkbox"
                                                   onChange={this.handleChecboxChange.bind(this, offer)}/>
                                        </td>
                                        <td style={{width: '5%'}}>{offer.index}</td>
                                        <td style={{width: '10%'}}>{offer.weight}g</td>
                                        <td style={{width: '70%'}}>{offer.name}</td>
                                        <td style={{width: '20%'}}>{offer.discount} Kč</td>
                                    </tr>
                                )
                            })}
                            </tbody>
                        </table>

                        <label className="sr-only" htmlFor="inlineFormInput">Name</label>
                        <input type="text" className="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput"
                               placeholder="Jméno" onChange={this.handleNameChange}/>

                        <label className="mr-sm-2" htmlFor="inlineFormCustomSelect">Budova</label>
                        <select className="custom-select mb-2 mr-sm-2 mb-sm-0" id="inlineFormCustomSelect"
                                onChange={(e) => this.setState({selectedBuild: e.target.value})}>
                            {options.map(option => {
                                return <option value={option} key={option}>{option}</option>
                            })}
                        </select>

                        <div className="form-check mb-2 mr-sm-2 mb-sm-0">
                            <label className="form-check-label">
                                <input className="form-check-input" type="checkbox"
                                       onChange={this.handleCheckedOrder}/> Objednám
                            </label>
                        </div>

                        <button type="submit" className="btn btn-secondary"
                                disabled={!this.isValid()}>Odeslat
                        </button>
                    </form>
                </div>
            </div>
        );
    }
}

export default Offer;

Upvotes: 1

Views: 416

Answers (3)

Mohammed Al-Reai
Mohammed Al-Reai

Reputation: 2786

Try to add it in the form submit function evt.preventDefault();}

handleSubmit=(eve)=>
{
  evt.preventDefault();
}

Tell me if it works or not.

Upvotes: 0

Mohit Yadav
Mohit Yadav

Reputation: 465

In addition to what maartendev's comment, to get the errors and result in component state you can write the handler as:

handleSubmit(evt) {
  evt.preventDefault();
  axios({
    method: 'post',
    url: '/order',
    headers: {},
    data: {
        name: this.state.name,
        food: this.state.selectedFoods,
        order: this.state.isChecked,
        build: this.state.selectedBuild
    }
   }).catch(({ response }) => this.setState({ errors: response.data }));
}

This will give you errors in this.state.errors which can be used in render method.

Upvotes: 2

MaartenDev
MaartenDev

Reputation: 5802

This is because the button submits the form and refreshes the page by default. This can be prevented by using evt.preventDefault();

handleSubmit(evt) {
    evt.preventDefault();
    axios({
        method: 'post',
        url: '/order',
        headers: {},
        data: {
            name: this.state.name,
            food: this.state.selectedFoods,
            order: this.state.isChecked,
            build: this.state.selectedBuild
        }
    });
};

Upvotes: 4

Related Questions