使用 Yup 进行图像字段验证

问题描述 投票:0回答:1

目前,我有我的 React 应用程序,我正在其中处理表单。我有一个图像字段,应该允许上传图像文件,如

jpeg
png
gif
等。但由于某种原因,它不起作用。我尝试了
.test()
方法是的。但它不起作用。

这是我的代码。

import React, { useState } from "react";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import {
  Grid,
  Row,
  Col,
  FormControl,
  Button,
  FormGroup,
  ControlLabel,
} from "react-bootstrap";
import { string, number } from "yup";
import * as Yup from "yup";
import { v4 as uuidv4 } from "uuid";
import { addPlace } from "../slice/touristPlacesSlice";
import "bootstrap/dist/css/bootstrap.min.css";
import "./FormComponent.css";

function FormComponent() {
  const place = useSelector((state) => state.touristPlace.touristPlace);
  const [touristPlace, setTouristPlace] = useState(
    place || {
      name: "",
      address: "",
      rating: "",
      type: "",
      picture: "",
      idx: uuidv4(),
    }
  );

  const dispatch = useDispatch();

  const [errorLog, setErrorLog] = useState({});

  const validationSchema = Yup.object().shape({
    name: Yup.string().required("Name of the place is required."),
    address: Yup.string().required("Address of the place is required."),
    rating: Yup.number()
      .required("Must have to be a number between 1 to 5")
      .positive()
      .min(1)
      .max(5),
    picture: Yup.string().required("Please select a valid image file."),
  });

  const handleReset = () => {
    setTouristPlace({
      name: "",
      address: "",
      rating: "",
      type: "",
      picture: null,
      idx: uuidv4(),
    });
    setErrorLog({});
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await validationSchema.validate(touristPlace, { abortEarly: false });
      dispatch(addPlace(touristPlace));

      setTouristPlace({
        name: "",
        address: "",
        rating: "",
        type: "",
        picture: null,
        idx: uuidv4(),
      });
      setErrorLog({});
    } catch (error) {
      const newErrorLog = {};
      error.inner.forEach(err => {
        newErrorLog[err.path] = err.message;
      });
      setErrorLog(newErrorLog);
    }
  };

  const handleChange = (e) => {
    if (e.target.type === "file") {
      setTouristPlace((prev) => ({
        ...prev,
        picture: URL.createObjectURL(e.target.files[0]),
      }));
    } else {
      const { name, value } = e.target;
      setTouristPlace((prevPlace) => ({
        ...prevPlace,
        [name]: value,
      }));
    }
  };

  return (
    <div>
      <Grid>
        <h1 className="text-center">Add a new Tourist Place</h1>
        <br />
        <FormGroup className="addForm">
          <Row>
            <Col xs={12} sm={2}>
              <ControlLabel>Name</ControlLabel>
            </Col>
            <Col xs={12} sm={10}>
              <FormControl
                type="name"
                placeholder="Name"
                name="name"
                value={touristPlace.name}
                onChange={handleChange}
              />
              {errorLog.name && <span style={{ color: "red" }}>{errorLog.name}</span>}
            </Col>
          </Row>
          <Row>
            <Col xs={12} sm={2}>
              <ControlLabel>Address</ControlLabel>
            </Col>
            <Col xs={12} sm={10}>
              <FormControl
                type="text"
                placeholder="Address"
                name="address"
                value={touristPlace.address}
                onChange={handleChange}
              />
              {errorLog.address && <span style={{ color: "red" }}>{errorLog.address}</span>}
            </Col>
          </Row>

          <Row>
            <Col xs={12} sm={2}>
              <ControlLabel>Rating</ControlLabel>
            </Col>
            <Col xs={12} sm={10}>
              <FormControl
                type="number"
                name="rating"
                value={touristPlace.rating}
                onChange={handleChange}
              />
              {errorLog.rating && <span style={{ color: "red" }}>{errorLog.rating}</span>}
            </Col>
          </Row>
          <Row>
            <Col xs={12} sm={2}>
              <ControlLabel>Type</ControlLabel>
            </Col>
            <Col xs={12} sm={10}>
              <FormControl
                componentClass="select"
                placeholder="select"
                name="type"
                onChange={handleChange}
              >
                <option value="select">Beach</option>
                <option value="other">Hill</option>
                <option value="other">Fountain</option>
                <option value="other">Landmark</option>
              </FormControl>
            </Col>
          </Row>

          <Row>
            <Col xs={12} sm={2}>
              <ControlLabel>Picture</ControlLabel>
            </Col>
            <Col xs={12} sm={10}>
              <FormControl
                type="file"
                style={{ width: "100%" }}
                name="picture"
                onChange={handleChange}
                accept='image/png, image/gif, image/jpeg'
              />
              {errorLog.picture && <span style={{ color: "red" }}>{errorLog.picture}</span>}
            </Col>
          </Row>
          <Row>
            <Col xsOffset={10}>
              <div className="button-group text-right">
                <Button bsStyle="success" onClick={handleSubmit}>
                  Submit
                </Button>
                <Button bsStyle="warning" onClick={handleReset}>
                  Reset
                </Button>
              </div>
            </Col>
          </Row>

          <Row>
            <Col xsOffset={10}>
              <Link
                to="/list"
                style={{ color: "#0aaaec" }}
                onClick={handleReset}
              >
                Back to Tourist Place List.
              </Link>
            </Col>
          </Row>
        </FormGroup>
      </Grid>
    </div>
  );
}

export default FormComponent;
reactjs forms yup
1个回答
0
投票

您正在尝试验证图片字段以确保仅接受有效的图像文件(jpeg、png、gif)。目前,您在图片字段上使用带有 string() 方法的 Yup 模式。但是,由于它是文件输入字段,因此您应该尝试使用 Yup 的 mix() 模式类型进行文件验证。尝试这样的事情,

  picture: Yup.mixed()
    .test(
      "fileType",
      "Please select a valid image type",
      (value) => value && ['image/jpeg', 'image/png', 'image/gif'].includes(value.type)
    )
    .required("Please select a valid image file.")
© www.soinside.com 2019 - 2024. All rights reserved.