1

I am new to react development. I am using redux to update my product. I had succeeded in updating the product from postman but I couldn't update from the admin panel. I think there is an issue in the front end as API is tested using postman and the backend is working. Kindly help me.

My Product component

import { Link } from "react-router-dom";
import "./Product.css";
import { useLocation } from "react-router-dom";
import axios from "axios";
import { Publish } from  '@mui/icons-material';
import { useSelector } from "react-redux";
import { updateProduct } from "../../Redux/apiCalls";
import { useDispatch } from "react-redux";
import { useState } from "react";




const Product = () => {
const location=useLocation();
const productId=location.pathname.split("/")[2];

const product=useSelector(state=>state.product.products.find(product=>product._id===productId))
const dispatch=useDispatch();

console.log(productId);
// const [title, setTitle]=useState("");
// const [desc, setDesc]=useState("");
// const [price, setPrice]=useState("");
// const [inStock, setInStock]=useState("");

const [inputs, setInputs]=useState({})



const handleChange=(e)=>{
    setInputs((prev) => {
        return { ...prev, [e.target.name]: e.target.value };
      });
}
console.log(inputs);
const handleUpdate=async()=>{

 
await updateProduct(productId, inputs , dispatch)


// await axios.put('http://localhost:5000/api/products/`$productId`', inputs, productId)
// .then(response=>console.log(response.data))


    }

    

return ( <>
     <div className="product">
      <div className="productTitleContainer">
        <h1 className="productTitle">Product</h1>
        <Link to="/newproduct">
          <button className="productAddButton">Create</button>
        </Link>
      </div>
      <div className="productTop">
  
          <div className="productTopRight">
              <div className="productInfoTop">
                  {/* <img src={product.img} alt="" className="productInfoImg" /> */}
                  <span className="productName">Product Name</span>
              </div>
              <div className="productInfoBottom">
                  <div className="productInfoItem">
                      <span className="productInfoKey">id:</span>
                      <span className="productInfoValue">{product._id}</span>
                  </div>
                  <div className="productInfoItem">
                      <span className="productInfoKey">sales:</span>
                      <span className="productInfoValue">5123</span>
                  </div>
                  <div className="productInfoItem">
                      <span className="productInfoKey">Price</span>
                      <span className="productInfoValue">{product.price}</span>
                  </div>
                  <div className="productInfoItem">
                      <span className="productInfoKey">in stock:</span>
                      <span className="productInfoValue">{product.inStock}</span>
                  </div>
              </div>
          </div>
      </div>
      <div className="productBottom">
          <form className="productForm">
              <div className="productFormLeft">
                  <label>Product Name</label>
                  <input type="text" placeholder={product.title} name="title"   onChange={handleChange} />
                  <label>Product Description</label>
                  <input type="text" placeholder={product.desc}  name="desc"   onChange={handleChange} />
                  <label>Product Price</label>
                  <input type="text" placeholder={product.price} name="price"    onChange={handleChange}/>
                  
                  <label>In Stock</label>
                  <select name="inStock" id="idStock"
                 onChange={handleChange}
                   > 
                      <option value="true">Yes</option>
                      <option value="false">No</option>
                  </select>
              </div>
              
              <div className="productFormRight">
                  <div className="productUpload">
                      <img src={product.img} alt="" className="productUploadImg" 
                   
                      />
                      <label for="file">
                          <Publish/>
                      </label>
                      <input type="file" id="file" style={{display:"none"}}      />
                  </div>
                  <button className="productButton"  onClick={(e)=>handleUpdate(e.preventDefault())}>Update</button>
              </div>
          </form>
  
      </div>
    </div>
    
    
    </> );
}
 
export default Product;

My Update component in Redux

    export const updateProduct = async (id, product, dispatch) => {
  dispatch(updateProductStart());
  try {
 const res = await userRequest.put(`/products/${id}`);
   
    dispatch(updateProductSuccess({ id, product }));
  } catch (err) {
    dispatch(updateProductFailure());
  }
};

 updateProductStart: (state) => {
      state.isFetching = true;
      state.error = false;
    },
    updateProductSuccess: (state, action) => {
      state.isFetching = false;
      state.products[
        state.products.findIndex((item) => item._id === action.payload.id)
      ] = action.payload.product;

    },
    updateProductFailure: (state) => {
      state.isFetching = false;
      state.error = true;
    },

My API

import { ConstructionOutlined } from "@mui/icons-material";
import axios from "axios";

const BASE_URL = "http://localhost:5000/api/";
const user = JSON.parse(localStorage.getItem("persist:root"))?.user;
const currentUser = user && JSON.parse(user).currentUser;
const TOKEN = currentUser?.accessToken;

// const TOKEN = JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser.accessToken;

export const publicRequest = axios.create({
  baseURL: BASE_URL,
});

export const userRequest = axios.create({
  baseURL: BASE_URL,
  headers: { token: `Bearer ${TOKEN}` },
});

My routes

router.put("/:id", verifyTokenAndAdmin, async (req, res) => {
  try {
    const updatedProduct = await Product.findByIdAndUpdate(
      req.params.id,
      {
        $set: req.body,
      },
      { new: true }
    );
res.status(200).json(updatedProduct)
  } catch (err) {
console.log("Can't update")
  }
});

Model

    const mongoose = require("mongoose");

const ProductSchema = new mongoose.Schema(
  {
    title: { type: String, required: true, unique: true },
    desc: { type: String, required: true },
    img: { type: String},
    categories: { type: Array },
    size: { type: Array },
    color: { type: Array },
    price: { type: Number, required: true },
    inStock: { type: Boolean, default: true },
  },
  { timestamps: true }
);

module.exports = mongoose.model("Product", ProductSchema);
Christian Baumann
  • 3,188
  • 3
  • 20
  • 37
  • have you tried to change your base URL from localhost to use local host ip? `http://127.0.0.1:5000/api/` – Anas Jun 19 '22 at 14:09
  • Open the network tab and check the request you made from the react app & compare it with the request you send from the postman. – Dilshan Jun 20 '22 at 05:36
  • I checked and this is the response in the network tab. `Request URL: http://localhost:5000/api/products/62a429456bcb1690eb416461 Request Method: OPTIONS Status Code: 204 No Content Remote Address: [::1]:5000` and I am sending a put request at ` http://localhost:5000/api/products/62a429456bcb1690eb416461` URL from postman ` – Adnan Ahmad Jun 23 '22 at 05:34
  • After sending update request I got this `Request URL: http://localhost:5000/api/products/62a429456bcb1690eb416461 Request Method: PUT Status Code: 403 Forbidden Remote Address: [::1]:5000 Referrer Policy: strict-origin-when-cross-origin` – Adnan Ahmad Jun 23 '22 at 05:41

1 Answers1

0

Browsers won't allow cross origin requests if backend doesn't send response with header

Access-Control-Allow-Origin: <current domain name> .

So at backend we need to send response with header Access-Control-Allow-Origin: localhost:3000

-> In express project:

Run npm install cors

Change express initialization like this

var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

This would add a header Access-Control-Allow-Origin: * to each response handled. This header says allow requests from browser within any website

Check more at

p2pdops
  • 505
  • 4
  • 11