首页 > 解决方案 > 快速发布请求将我重定向到 json 页面,而不是显示成功或错误消息 toast

问题描述

我正在使用 MERN 堆栈制作一个 crud 应用程序来练习我的技能,因为我对此很陌生它在 Postman 上运行良好,但是当我将数据传递到前端(React 和 Redux)时,它也运行良好,但浏览器没有使用 toastfy 向我显示成功或错误消息,而是将我重定向到带有 json 数据的新页面我发了

PS。我尝试使用 formik 处理我的表单状态和错误,但它没有将我重定向到 json 页面,它显示了我从 toast 后端发送的错误消息,但对我不起作用,因为 formik 真的很复杂处理文件,所以我用简单的方法做到了

// multer 中间件来处理图像

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./uploads/");
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname);
    }
});

const fileFilter = (req, file, cb) => {
    // reject a file
    if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
        cb(null, true);
    } else {
        cb(null, false);
    }
};

const upload = multer({ storage, fileFilter });

这是验证和使用后端,它是一组方法

const createProduct = [
//validate product that it's not empthy
// then sanitize it with trima and escape
body("name")
    .isLength({ min: 5 })
    .withMessage("Must be at least 2 letters")
    .trim()
    .escape(),
body("description")
    .isLength({ min: 20 })
    .withMessage("Must be at least 10 letters")
    .trim()
    .escape(),
body("category")
    .isLength({ min: 1 })
    .withMessage("This field is required")
    .trim()
    .escape(),
body("price")
    .isLength({ min: 1 })
    .withMessage("Must be at least 1 number")
    .isNumeric()
    .withMessage("Must be Numeric")
    .trim()
    .escape(),
body("numberInStock")
    .isLength({ min: 1 })
    .withMessage("Must be at least 1 number")
    .isNumeric()
    .withMessage("Must be Numeric")
    .trim()
    .escape(),

// continue process after validation
(req, res, next) => {
    console.log(req.file);

    // get the validation errors from the request
    const errors = validationResult(req);

    // create new product after being validated and sanitized
    let newProduct = new Product({
        name: req.body.name,
        description: req.body.description,
        category: req.body.category,
        price: req.body.price,
        numberInStock: req.body.numberInStock,
        productImage: req.file.path
    });

    // if there are validation errors send them as json
    if (!errors.isEmpty()) {

        //i only show the first error
        let field = errors.errors[0].param;
        let message = errors.errors[0].msg;
        let errorMessage = field + " " + message;

        res.status(400).json({
            message: errorMessage
        });
    } else {
        newProduct.save(function (err, product) {
            if (err) {
                console.log(err);

                res.json({
                    message: "Couldn't create please try again"
                });
            } else {
                res.redirect({
                    message: "Created Successfully",
                    product
                });
            }
        });
    }
}
];

处理路线

router.post("/api/product/create",upload.single("productImage"), createProduct);

//添加产品动作

export const addProduct = product => dispatch => {
return new Promise((resolve, reject) => {
    axios
        .post("/api/product/create", product)
        .then(res => {
            let newProduct = res.data.product;
            let successMessage = res.data.message;

            dispatch(addProductSuccess(newProduct, successMessage));
            resolve(successMessage);
        })
        .catch(error => {
            console.log(error.message);

            dispatch(addProductFailure(error));
            reject(error.message);
        });
});
};

const addProductSuccess = (product, successMessage) => {
    return {
        type: ADD_PRODUCT_SUCCESS,
        payload: {
            product,
            successMessage
        }
    };
};

const addProductFailure = error => {
    return {
        type: ADD_PRODUCT_FAILURE,
        payload: {
            error
        }
    };
};

//添加产品表单

function AddProductForm() {
// importing categories and laoding state from out store
const { categories, error, loading } = useSelector(
    state => state.categoriesss
);

const [state, setState] = useState({
    name: "",
    description: "",
    category: "",
    price: "",
    numberInStock: "",
    productImage: ""
});

const handleChange = e => {
    const { name, value } = e.target;
    setState(prevState => ({
        ...prevState,
        [name]: value
    }));
};

// react redux method to dispatch our functions
const dispatch = useDispatch();

// fetch all the the categories with dispatch before our component render
useEffect(() => {
    dispatch(fetchCategories());
}, [dispatch]);


// handle submit our form
const handleSubmitt = product => {

    dispatch(addProduct(product))
        .then(res => {
            toast.success(res, {
                position: toast.POSITION.BOTTOM_LEFT,
                transition: Slide
            });
        })
        .catch(err => {
            toast.error(err, {
                position: toast.POSITION.BOTTOM_LEFT,
                autoClose: false
            });
        });
};

let newProduct = {
    name: state.name,
    description: state.description,
    category: state.category,
    price: state.price,
    numberInStock: state.numberInStock,
    productImage: state.productImage
};

return (
    <Container>
        <form
            action='/api/product/create'
            method='post'
            enctype='multipart/form-data'
            onSubmit={() => handleSubmitt(newProduct)}>
            <div className='form-group'>
                <input
                    className='form-control mb-2'
                    type='text'
                    placeholder='Enter Product name'
                    name='name'
                    required
                    onChange={handleChange}
                />
            </div>
            <div className='form-group'>
                <input
                    className='form-control mb-2'
                    as='textarea'
                    placeholder='Enter Product description'
                    name='description'
                    required
                    onChange={handleChange}
                />
            </div>
            <div className='form-group'>
                <select
                    className='custom-select mb-2'
                    name='category'
                    required
                    onChange={handleChange}>
                    {loading && <option>loading...</option>}
                    {categories.map(cat => {
                        return (
                            <option key={cat._id} value={cat._id}>
                                {cat.name}
                            </option>
                        );
                    })}
                </select>
            </div>
            <div className='form-group'>
                <input
                    className='form-control mb-2'
                    type='text'
                    placeholder='Enter Product price'
                    name='price'
                    required
                    onChange={handleChange}
                />
            </div>
            <div className='form-group'>
                <input
                    className='form-control mb-2'
                    type='text'
                    placeholder='Enter Product numberInStock'
                    name='numberInStock'
                    required
                    onChange={handleChange}
                />
            </div>
            <div className='form-group'>
                <input
                    className='custom custom-file mb-2'
                    type='file'
                    name='productImage'
                    required
                    onChange={handleChange}
                />
            </div>
            <Button
                variant='primary'
                type='submit'
                onClick={() => handleSubmitt(newProduct)}>
                Submit{" "}
            </Button>{" "}
        </form>
    </Container>
    );
}

export default AddProductForm;

请求成功完成后的结果

请求完成后的结果错误

标签: node.jsreactjsexpressreduxmern

解决方案


尝试这个

<form
    action='/api/product/create'
    method='post'
    enctype='multipart/form-data'
    onSubmit={(e) => {
        handleSubmitt(newProduct)
        e.preventDefault()
}>

推荐阅读