TransWikia.com

React : How do you write id to have dynamic axios requests

Stack Overflow Asked by Junaka on October 19, 2020

I’m new to React, and despite many attempts I can’t figure out how to set my id dynamically in axios requests in my edit-form.

I tried to set the axios requests with a static number just to test my edit-form, I can log my object but when I submit it deletes the product data instead of updating with the new data because the id is undefined.

I think I just need to find out what to write in my componentDidMount and handleSubmit to catch the id.
For example ${this.state.product.id} is undefined, why isn’t it working?

It’s my first question, so I hope I am clear and tell me if you need more code.

EditForm

import React, { Component } from 'react';
import { withRouter } from 'react-router';
import axios from 'axios';

import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import Form from 'react-bootstrap/Form';
import Col from 'react-bootstrap/Col';
import FormControl from 'react-bootstrap/FormControl';
import Button from 'react-bootstrap/Button';

class EditForm extends React.Component {

    constructor(props) {
        super(props);
        this.state = { product: [] };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    };
    
    componentDidMount = () => {
        axios
        .get(`/products/edit-form/${this.props.match.params.id}`)
        .then(response => {
            console.log(response.data.products);
            this.setState({
                product: response.data.products
            })
        });
    
    };

    handleChange(e) {
        this.setState({id: e.target.value})
        this.setState({reference: e.target.value})
        this.setState({designation: e.target.value})        
    }

    handleSubmit(e) {
        e.preventDefault();     
        const data = { 
        id: this.state.product.id,
        reference: this.state.product.reference,
        designation: this.state.product.designation        
        };

        axios
        .post(`/products/${this.props.match.params.id}`, data )
        .then(res => console.log(res))      
        .catch(err => console.log(err));
    };
 
    renderForm() {
        return this.state.product.map((product, index) => {
            const { id,reference,designation } = product
        return(
            <>         
            <Form className="post" onSubmit={this.handleSubmit}>
                <Form.Row>
                    <Form.Group as={Col} controlId="formGridReference">
                    <Form.Label>Reference</Form.Label>
                    <Form.Control type="text" value={this.state.product.reference} 
                        onChange={this.handleChange} name="reference" placeholder={reference} />
                    </Form.Group>

                    <Form.Group as={Col} controlId="formGridDesignation">
                    <Form.Label>Designation</Form.Label>
                    <Form.Control type="text" value={this.state.product.designation} 
                        onChange={this.handleChange} name="designation" placeholder={designation} />
                    </Form.Group>
                </Form.Row>                

                <Button variant="primary" type="submit">
                    Submit
                </Button>
            </Form>
            </>
            );
        })
    }
    
    render() {
        return (
            <div>
                <h1>Formulaire de modification</h1>
                {this.renderForm()}
            </div>        
        );
    }
}

export default withRouter(EditForm);

App.js

class App extends Component {
    render() {
        return (
            <React.Fragment>
                <NavBar />            
                <Router>
                    <Route exact path="/" component={Products}/>
                    <Route path="/edit-form/:productId" component={EditForm}/>
                </Router>
            </React.Fragment>  

        );
    }
}

Products

import React, { Component } from 'react';
import Table from 'react-bootstrap/Table';
import Button from 'react-bootstrap/Button';
import { Link } from 'react-router-dom';
import axios from 'axios';

const headings = [
    'id','reference','designation'
];

export default class Products extends Component {

    constructor(props) {
        super(props);
        this.state = {
            products: []
        };
    };

    componentDidMount = () => {
        axios.get("/products").then(response => {
            console.log(response.data.products);
            this.setState({
                products: response.data.products
            })
        });
    };
 
    renderTableHeader() {       
        return headings.map((key, index) => {
        return <th key={index}>{key.toUpperCase()}</th>
        })
    } 

    renderProductData() {
        return this.state.products.map((product, index) => {
            const { id,reference,designation } = product
            return (
                <tr key={id}>
                    <td>
                        {id}
                        <Link to={`/edit-form/${id}`}>Modifier</Link>
                    </td>
                    <td>{reference}</td>
                    <td>{designation}</td>                               
                </tr>
            )
        })
    }
 
    render() {
        return (
            <div>
                <h1 id='title'>Produits</h1>
                <Table striped bordered hover id='products'>
                    <thead>
                        {this.renderTableHeader()}
                    </thead>
                    <tbody>
                        {this.renderProductData()}
                    </tbody>
                </Table>
            </div>
        );
    }
}

Async functions

// productController.js

const getProduct = async (req, res) => 
{
    const { productId } = req.params;
    const product = await productDb.getProduct(productId);
    res.status(200).send({ products: product.rows });    
};

const postProduct = async (req, res) => 
{
    const { productId } = req.params;
    const { reference,designation } = req.body;
    await productDb.updateProduct(productId, reference, designation);
    res.status(200).send(`Le produit reference ${reference} a été modifié`);  
    console.log(`Le produit reference ${reference} a été modifié`); 


// productDb.js

const getProduct = async (id) =>
{
    const connection = new DbConnection();
    return await connection.performQuery(`SELECT * FROM produits WHERE id=${id}`);
};

const updateProduct = async (id, reference, designation) =>
{
    const connection = new DbConnection();
    await connection.performQuery("UPDATE produits SET reference=?, designation=? WHERE id=?", 
    [reference, designation, id]);
};

Thank you

One Answer

In your Products.js, you are using links to open up your EditForm component. So, for you to be able to access the product id, you need to wrap your EditForm component with the withRouter hoc from the react-router library. This hoc will then make the match prop available to your EditForm component.

So, you need to add react-router to your dependencies by running this:

yarn add react-router **OR** npm install react-router

Then add it to your import statements in EditForm.js

import { withRouter } from 'react-router';

And then inside componentDidMount, you should be able to access the id by doing this:

this.props.match.params.id

You also need to change your class definition to:

class EditForm extends React.Component

And then export it like this:

export default withRouter(EditForm)

I assume in your routes file, you must have a route that is defined like this:

<Route path="/edit-form/:id" component={EditForm} />

Correct answer by Chukwuemeka Inya on October 19, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP