[Fixed] Error: Cannot set headers after they are sent to the client – when i use axios in react not with postman

Issue

When I make a request using postman to the server, I don’t get the "Cannot set headers after they are sent to the client. But when I integrate with react.js, i keep getting the error. I would for someone to help look for the error. Thanks. Thanks in advance."

Cart.js (client)

import React, { Fragment, useEffect, useState } from 'react'
import { Redirect } from 'react-router-dom';
import Header from '../../components/Header/Header'
import './Cart.css'
import axios from 'axios'
import Loader from '../../components/Loader/Loader';
import {toast} from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import CartProduct from '../../components/CartProduct/CartProduct';
import { Link } from 'react-router-dom';
import OrderDetails from '../../components/CartPricing/CartPricing';
import Empty from '../../components/Empty/Empty';

toast.configure();
    
function Cart({title, clientRootUrl, apiRootUrl, loggedInStatus, token, errorMessage, cartNum,decreaseCartNum, requireAuth}) {

    document.title = `Cart - ${title}`;

    /** 
     * To 2 d.p.
     * Text: parseFloat("123.456").toFixed(2)
     * Number: num.toFixed(2);
     */

    const [isLoading, setIsLoading] = useState(true);
    const [cartProducts, setCartProducts] = useState([]);
    const [allowed, setAllowed] = useState(false);
    const [subTotals, setSubTotals] = useState(0);
    const [delivery, setDelivery] = useState(0); // use request to get details
    const [total, setTotal] = useState(0);
    const [all,setAll] = useState(false);

    
    /** Pass the ffg data to App.js
     * cart
     * subtotal
     * delivery
     * total
     */

    useEffect(() => {
        // setIsLoading(true);
        axios.post(`${apiRootUrl}miscellaneous/fee`, 
        {
            subtotal: subTotals
        },
        {
        headers: {
            Authorization: `Bearer ${token}`
        }
        })
        .then(({data})=>{
            // setIsLoading(false);
            setDelivery(data.cost);
        })
        .catch(err=>{
            // setIsLoading(false);
            console.log(err)
            // toast.error(errorMessage, {
            //     position: toast.POSITION.BOTTOM_RIGHT
            // })
        })

    }, [total])

    useEffect(() => {
        setTotal(subTotals + delivery);
    }, [delivery])

    useEffect(()=>{
        axios.get(`${apiRootUrl}cart/`, {
            headers: {
                Authorization: `Bearer ${token}`
            }
        })
        .then(({data})=>{
            let cartItems = data;
            // setCartProducts(data);
            // console.log(cartItems)

            if(cartItems.length < 1) {
                setIsLoading(false);
            } else {
                cartItems.map(({id,productId,quantity})=>{
                    // cart: id, productId // product details
                    axios.get(`${apiRootUrl}product/${productId}`)
                    .then(({data})=>{
                        setIsLoading(false);
                        setAllowed(true); // show details            
                        let product = data;
                        // no storing the previous one being asynchronous, so we have to use the previous in the argument
                        setCartProducts(prevCartProducts => [ ... prevCartProducts, {
                            cartId:id,
                            quantity:quantity,
                            id:product.id,
                            categoryId: product.categoryId,
                            name: product.name,
                            description: product.description,
                            image: product.image,
                            price: product.price
                        }]);

                    })
                    .catch(err=>{
                        setIsLoading(false);
                        console.log(err)
                        // toast.error(errorMessage, {
                        //     position: toast.POSITION.BOTTOM_RIGHT
                        // })
                    })
                })
            }
        })

        .catch(err=>{
            setIsLoading(false);
            // toast.error(errorMessage, {
            //     position: toast.POSITION.BOTTOM_RIGHT
            // })      
            console.log(err)
        })
    },[apiRootUrl])


    function delCartItem(cartId) {
        


        // delete from DB
        setIsLoading(true);
        axios.delete(`${apiRootUrl}cart/${cartId}`,{
            headers: {
                Authorization: `Bearer ${token}`
            }
        })
        .then(({data})=>{
            setIsLoading(false);
            if(data.error === 0) {
                toast.success(data.message, {
                    position: toast.POSITION.BOTTOM_RIGHT
                })
                setCartProducts([...cartProducts.filter(cartProduct=>cartProduct.cartId !== cartId)]);

                // reduce cartNum by 1
                decreaseCartNum();
            } else {
                toast.error(errorMessage, {
                    position: toast.POSITION.BOTTOM_RIGHT
                })
            }
            if(cartProducts.length-1 < 1) {
                setAllowed(false);
            } else {
                // as products are being deleted , RECALCULATE VALUES

                // total prices will change authomatically
            }
        })
        .catch(err=>{
            setIsLoading(false);
            // toast.error(errorMessage, {
            //     position: toast.POSITION.BOTTOM_RIGHT
            // })
            console.log(err)

        })
    }

    function addSubTotals(subTotal) {
        // setSubTotals(prevSubTotals=>prevSubTotals+subTotal);
    }


    useEffect(() => {
        /** Get The Delivery Cost of The Products @ The Good Time */

        setTotal(subTotals+delivery);


    }, [subTotals])

    useEffect(() => {
        let sum = 0;
        cartProducts.map((p)=>{
            let subtotal = Number(p.price) * Number(p.quantity);
            sum+=subtotal;
        })
        setSubTotals(sum);   

        

    }, [cartProducts])

    function calculateNewSubTotalAndTotal(newQuantity, cartId) {

        // update quantity and update of the specific cartId
        const elementsIndex = cartProducts.findIndex(item=>item.cartId === cartId)  
        let newCartProducts = [...cartProducts];
        newCartProducts[elementsIndex] = {...newCartProducts[elementsIndex], quantity:newQuantity}
        setCartProducts(newCartProducts);
    }

    // function payWithPaystack(e) {
    //     e.preventDefault();
    //     let handler = PaystackPop.setup({
    //       key: 'sk_test_f12711e9277e1a27aba8e58f3394b9717098efaf', // Replace with your public key
    //       email: "[email protected]",
    //       amount: 1200 * 100,
    //       ref: ''+Math.floor((Math.random() * 1000000000) + 1), // generates a pseudo-unique reference. Please replace with a reference you generated. Or remove the line entirely so our API will generate one for you
    //       // label: "Optional string that replaces customer email"
    //       onClose: function(){
    //         alert('Window closed.');
    //       },
    //       callback: function(response){
    //         let message = 'Payment complete! Reference: ' + response.reference;
    //         alert(message);
    //       }
    //     });
    //     handler.openIframe();
    //   }


    return (
        <React.Fragment>
             {requireAuth()}
            {isLoading && <Loader />}
           
            <Header title = {title} clientRootUrl = {clientRootUrl} loggedInStatus = {loggedInStatus} cartNum = {cartNum} token = {token} />

            <br />
            <br />
            
            <div className = "small-container cart-page">

                {
                    (cartProducts.length > 0) && (
                        <table>
                            <tr>
                                <th>Product</th>
                                <th>Quantity</th>
                                <th>Subtotal</th>
                            </tr>

                            {
                                cartProducts.map(({cartId,quantity,id,categoryId,name,description,image,price,out_of_stock})=><CartProduct key = {id} cartId = {cartId} quantity = {quantity} id = {id} categoryId = {categoryId} name = {name} description = {description} image = {image} price = {price} out_of_stock = {out_of_stock} apiRootUrl = {apiRootUrl} token = {token} errorMessage = {errorMessage} delCartItem = {delCartItem} addSubTotals = {addSubTotals} calculateNewSubTotalAndTotal = {calculateNewSubTotalAndTotal} />)
                            }
                        </table>
                    )
                }

                {
                    (cartProducts.length < 1) && (
                        <Fragment>
                            <Empty clientRootUrl = {clientRootUrl}>Ahh! Your cart seems empty.</Empty>
                        </Fragment>
                    )
                }
        
                { (allowed) && (
                    <OrderDetails subTotals = {subTotals} delivery = {delivery} total = {total} >
                        <Link to = {`/checkout`} className = "btn">Proceed to Checkout</Link>
                    </OrderDetails>
                )}
                
                <br />
                <br />
                <br />
            </div>
        </React.Fragment>
    )
}

export default Cart

app.js (server)

const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const path = require('path');

const userRoutes = require('./api/routes/user');
const adminRoutes = require('./api/routes/admin');
const categoryRoutes = require('./api/routes/category');
const productRoutes = require('./api/routes/product');
const orderRoutes = require('./api/routes/order');
const marketRoutes = require('./api/routes/market');
const searchRoutes = require('./api/routes/search');
const cartRoutes = require('./api/routes/cart');
const miscellaneousRoutes = require('./api/routes/miscellaneous');

app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

app.use((req,res,next) => {
    res.header("Access-Control-Allow-Origin","*"); // change later
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization"
    );
    // res.header("Cache-Control", 'no-cache');
    if(req.method === 'OPTIONS') {
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
        res.status(200).json({});
    }
    next();
});

app.use('/user', userRoutes);
app.use('/admin', adminRoutes);
app.use('/category', categoryRoutes);
app.use('/product', productRoutes);
app.use('/order', orderRoutes);
app.use('/market', marketRoutes);
app.use('/search', searchRoutes);
app.use('/cart', cartRoutes);
app.use('/miscellaneous', miscellaneousRoutes);


// sample code to create static filepath
// app.use('/uploads', express.static('img'));

app.use('/uploads', express.static('uploads'));
app.use(express.static(path.join(__dirname,'public')));

app.use((req,res,next) => {
     const error = new Error('Not found');
     error.status = 404;
     next(error);
 });

 app.use((error,req,res,next) => {
     res.status(error.status || 500);
     res.json({
         error: {
             message:error.message 
         }
     });
 });

module.exports = app;           

cart.js (server(controller))

const pool = require('../../utils/pool');

exports.cart_get_all_for_user = (req,res,next) => {
    const tokenUserId = req.userData.userId;
    // const tokenEmail = req.userData.email;

    // if(userId == tokenUserId || tokenEmail === process.env.adminEmail) {
        pool.getConnection(function(err,conn){
            if(err) {
                return res.status(500).json({error:'An error occured. Please try again!'});
            } else {
                conn.query(`select * from cartSchema where userId = ?`, [tokenUserId], function(err,result){
                    conn.release();
                    if(err) {
                        return res.status(500).json({error:'An error occured. Please try again!'});
                    } else {
                        return res.status(200).json(result);
                    }
                });
            }
        });

        // res.end();
    // } else {
    //     res.status(401).json({error:'No authorization!'});
    // }
}

exports.add_to_cart = (req,res,next) => {
    const { productId, quantity } = req.body;
    const { userId } = req.userData;

    pool.getConnection(function(err,conn){
        if(err) {
            return res.status(500).json({error:'An error occured. Please try again!'});
        } else {
            pool.getConnection(function(err,conn){
                if(err) {
                    return res.status(500).json({error:'An error occured. Please try again!'});
                } else {
                    conn.query(`select * from cartSchema where ( productId = ?) and ( userId = ? )`, [ productId,userId], function(err,cart_product){
                        // conn.release();
                        if(err) {
                            return res.status(500).json({error:'An error occured. Please try again!'});
                        } else {
                            if(cart_product.length > 0) {

                                // update quantity in cart
                                conn.query(`update cartSchema set quantity = ? where ( productId = ?) and ( userId = ? )`, [quantity,productId,userId], function(err,result){
                                    if(err) {
                                        return res.status(500).json({error:'An error occured. Please try again!'});
                                    } else {
                                        return res.status(200).json({error:455,message:'Product already exists in cart but the quantity has been updated'});
                                    } 
                                });

                            } else {
                                conn.query(`insert into cartSchema (userId, productId, quantity) values (?,?,?)`, [userId,productId, quantity], function(err,result){
                                    conn.release();
                                    if(err) {
                                        return res.status(500).json({error:'An error occured. Please try again!'});
                                    } else {
                                        return res.status(200).json({
                                            error: 0,
                                            message: 'Product has been added to cart',
                                            id: result.insertId,
                                            userId,
                                            productId,
                                            quantity
                                        });
                                    }
                                });
                            }
                        }
                    })
                }
            });
        }
    }); 
}

// update quantity
exports.update_cart_product_details = (req,res,next) => {
    const {cartId} = req.params;
    const {quantity} = req.body;
    const {userId} = req.userData;

    /** 
     * check if cartItem exists <i>
     * check if the user is authorized to change <i>
     * update cartItem
     * give success message
     */
    pool.getConnection((err, conn) => {
            if (err) {
                return res.status(500).json({ error: 'An error occured. Please try again!' });
            } else {
                conn.query(`select * from cartSchema where id = ? and userId = ?`, [cartId,userId], (err,cartItem) => {
                    if(err) {
                        return res.status(500).json({ error: 'An error occured. Please try again!' });
                    } else {
                        console.log(cartItem)
                        if(cartItem.length < 1) {
                            return res.status(500).json({ error: 'An error occured. Please try again!' }); // The CartItem you're trying to update does not exist
                        } else {
                            conn.query(`update cartSchema set quantity = ? where ( id = ? and userId = ? )`, [quantity,cartId,userId], (err,result)=>{
                                conn.release();
                                if(err) {
                                    return res.status(500).json({ error: 'An error occured. Please try again!' });
                                } else {
                                    return res.status(200).json({error:0,message:"Quantity updated successfully"});
                                }
                            })
                        }
                    }
                });
            }
        })
}

exports.remove_from_cart = (req,res,next) => {
    const { cartId } = req.params;
    const {userId} = req.userData;

    pool.getConnection(function(err,conn){
        if(err) {
            return res.status(500).json({error:'An error occured. Please try again!'});
        } else {

            conn.query(`select * from cartSchema where id = ? and userId = ?`, [cartId,userId], (err,cartItem)=>{
                if(err) {
                    return res.status(500).json({ error: 'An error occured. Please try again!' });
                } else {
                    if(cartItem.length < 1) {
                        return res.status(500).json({ error: 'An error occured. Please try again!' }); // The CartItem you're trying to update does not exist
                    } else {
                        conn.query(`delete from cartSchema where id = ?`, [cartId], function(err,result){   
                            conn.release();
                            if(err) {
                                return res.status(500).json({error:'An error occured. Please try again!'});
                            } else {
                                return res.status(200).json({error:0,message:'Product successfully removed from cart'});
                            }
                        });
                    }
                }
            })

            
        }
    });
}

miscellaneous.js


exports.city_cost = (req,res,next) => {
    const {city} = req.params;
    console.log(city)
    return res.status(200).json({
        fee:checkLocationFee(city)
    })    
}

exports.delivery_cost = (req,res,next) => {
    
    const {userId} = req.userData;

    /** Get the city of the user */
    pool.getConnection((err,conn)=>{
        if(err) {
            logisticFees = logisticDefaultFee;
        } else {
            conn.query(`select * from userSchema where id = ?`, [userId], (err,user)=>{
                if(err) {
                    logisticFees = logisticDefaultFee;
                } else {
                    logisticFees = checkLocationFee(user[0].city); 
                }
            });
        }
    });

    console.log(logisticFees)

    // const logisticFees = 1000; /** logistic fees varies based on LOCATION */

    const { subtotal } = req.body;

    /** FoodNet Logic */
    let FoodNetFees;

    if(subtotal < 1000) {   
        FoodNetFees = ((2.5/100)*subtotal) + 100;  // 1.5 (down)
    } else if(subtotal <= 5000) {
        FoodNetFees = ((3/100)*subtotal) + 100; 
    } else if(subtotal > 5000 && subtotal <= 50000){
        FoodNetFees = ((3.5/100)*subtotal) + 100;
    } else { // above 50000
        FoodNetFees = ((4/100)*subtotal) + 100;
    }
    /** ../end */

    const paystackPaymentFee = ( subtotal + FoodNetFees + logisticFees ) * (1.5/100);

    const paystackTransferFee = 10; // off transfer made to them

    const totalCost = FoodNetFees + logisticFees + paystackPaymentFee + paystackTransferFee; // err to add subtotal

    return res.status(200).json({
        cost: totalCost
    })
}

exports.verify_transaction = (req,res,next) => {

    const {userId} = req.userData;

    pool.getConnection((err,conn)=>{
        if(err) {
            logisticFees = logisticDefaultFee;
        } else {
            conn.query(`select * from userSchema where id = ?`, [userId], (err,user)=>{
                if(err) {
                    logisticFees = logisticDefaultFee;
                } else {
                    logisticFees = checkLocationFee(user[0].city); 
                }
            });
        }
    });

    const { reference } = req.params;

    /** Verify Transaction (1) */
    const promise = paystack.verifyTransaction({
        reference
    })

    promise.then(function ({body}){
        if(body.data.status === 'success') {
            /** Create Transfer Recepient (2) */
            const promise2 = paystack.createTransferRecipient({
                type:"nuban",
                name: logisticName,
                account_number:logisticAccNumber,
                bank_code:logisticBankCode,
                currency:"NGN"
            })
            promise2.then(function({body}){
                if(body.data.active === true) {
                    /** Make Transfer with Recipient(3) */
                    // store recipient_code
                    const recipient_code = body.data.recipient_code;
                    console.log(recipient_code)
                    
                    /** JUST FOR DEVELOPMENT MODE ( REMOVE IN PRODUCTION MODE ) */
                    return res.status(200).json({error:0});

                    /** FOR PRODUCTION MODE BELOW */
                    // initiate transfer
                    const promise3 = paystack.initiateTransfer({
                        source:"balance",
                        reason: logisticReason,
                        amount: 900 * 100,
                        recipient: recipient_code,
                        reference: Math.floor((Math.random() * 1000000000) + 1)
                    })
                    promise3.then(function({body}){
                        if(body.data.status === "success") {
                            // will only work with real transactions
                            res.status(200).json({error:0})
                        } else {
                            /** Handle Error */
                            return res.status(500).json({error:'An error occured. Please try again!'})
                        }
                    }).catch(function(err){
                        /** Handle Error */
                        return res.status(500).json({error:'An error occured. Please try again!'})
                    });
                    /** FOR PRODUCTION MODE ABOVE */

                } else {
                    /** Handle Error */
                    return res.status(500).json({error:'An error occured. Please try again!'})
                }
            })
        } else {
            /** Handle Error */
            // console.log(2)  
            return res.status(500).json({error:'An error occured. Please try again!'})
        }
    }).catch(function(err){
        /** Handle Error */
        return res.status(500).json({error:'An error occured. Please try again!'})
    })
    // put return in all response
}

Solution

The problem got solved. I was making multiple requests to the server being asynchronous code. So i just nested my requests to the stay in the safe space and all worked perfectly.

Leave a Reply

(*) Required, Your email will not be published