2

我正在尝试在反应中完成一个表单,该表单具有上传图像的子组件(进行预览并做得更漂亮)但问题是我无法访问孩子的 useState 我需要的图像在哪里发送到后端。

这是子组件的代码,在 useState 中我需要通过父组件访问图像:

import React, { useState, Fragment } from "react";
import {
  Layout,
  Container,
  BoxUpload,
  ContainerUploadImage,
  TextUploadImage,
  LabelUploadImage,
  ImagePreview,
} from "./ImageUploadElements";
import UploadPhoto from "../../../images/upload.svg";
import CloseIcon from "../../../images/close.svg";

const ImageUpload = ({text}) => {
  const [image, setImage] = useState("");
  const [isUploaded, setIsUploaded] = useState(false);

  const handleImageChange = (e) => {
    if (e.target.files && e.target.files[0]) {
      let reader = new FileReader();

      reader.onload = (e) => {
        setImage(e.target.result);
        setIsUploaded(true);
      };
      reader.readAsDataURL(e.target.files[0]);
    }
  };

  return (
    <Layout>
      <Container>
        <h2>{text}</h2>
        <BoxUpload>
          <div className="image-upload">
            {isUploaded ? (
              <ImagePreview>
                <img
                  className="close-icon"
                  src={CloseIcon}
                  alt="CloseIcon"
                  onClick={() => {
                    setIsUploaded(false);
                    setImage(null);
                  }}
                />
                <img
                  src={image}
                  className="uploaded-image"
                  draggable={false}
                  alt="progress-uploaded"
                />
              </ImagePreview>
            ) : (
              <Fragment>
                <LabelUploadImage htmlFor="upload-input">
                  <ContainerUploadImage
                    src={UploadPhoto}
                    alt="Upload Icon"
                    draggable={false}
                  />
                  <TextUploadImage>Click to upload image</TextUploadImage>
                </LabelUploadImage>
                <input
                  type="file"
                  name="upload-input"
                  accept=".jpg,.jpeg,.gif,.png,.mov,.mp4"
                  onChange={handleImageChange}
                />
              </Fragment>
            )}
          </div>
        </BoxUpload>
      </Container>
    </Layout>
  );
};

export default ImageUpload;

在该上传表单组件中,我需要访问该图像以将其与 axios 一起发送到后端:

import React, { Fragment, useState } from "react";
import {
  Container,
  FormWrap,
  FormContent,
  Form,
  FormH1,
  FormLabel,
  FormInput,
  FormButton,
  FormErrorWrap,
  FormError,
  FormErrorText,
  PhotoWrap
} from "./UploadElements";
import ImageUpload from "../ImageUpload";
import { frontPhotoText, sidePhotoText, backPhotoText } from "./Data";

const Upload = () => {
  const [weight, setWeight] = useState("");
  

  const [uploadErrors, setUploadErrors] = useState([{}]);

  const upload  = (e) => {
    e.preventDefault();
    // Here will go the axios petición with the wight and the three images uploaded.
  }

  return (
    <Fragment>
      <Container>
        <FormWrap>
          <FormContent>
            <Form onSubmit={upload}>
              <FormH1>Upload New Progress</FormH1>
              <FormLabel htmlFor="weight">Weight</FormLabel>
              <FormInput
                onChange={(e) => setWeight(e.target.value)}
                type="number"
                value={weight}
                id="weight"
                required
              />
              <PhotoWrap>
                <ImageUpload {...frontPhotoText}/>
                <ImageUpload {...sidePhotoText}/>
                <ImageUpload {...backPhotoText}/>
              </PhotoWrap>
              <FormErrorWrap>
                {uploadErrors ? (
                  uploadErrors.map((err, index) => (
                    <FormError key={index}>
                      <FormErrorText>{err.msg}</FormErrorText>
                    </FormError>
                  ))
                ) : (
                  <Fragment></Fragment>
                )}
              </FormErrorWrap>
              <FormButton>Upload</FormButton>
            </Form>
          </FormContent>
        </FormWrap>
      </Container>
    </Fragment>
  );
};

export default Upload;

但是我不知道如何通过父母获得这些图像,如果有人可以帮助我将非常感激,谢谢!

4

1 回答 1

2

您可以使用forwardRefuseImperativeHandle的组合从子组件中公开父组件可以调用的函数。

Child - 导入和装饰子组件,forwardRef并使用useImperativeHandle来公开返回当前状态的getImage函数。image

import React, { useState, Fragment, forwardRef } from "react";
...

const ImageUpload = forwardRef(({text}, ref) => {
  const [image, setImage] = useState("");
  const [isUploaded, setIsUploaded] = useState(false);

  useImperativeHandle(ref, () => ({
    getImage: () => image,
  }));

  const handleImageChange = (e) => {
    ...
  };

  return (
    ...
  );
});

Parent - 创建一个 React ref 以传递给回调,ImageUpload并在回调中访问当前 ref 值并调用函数。

import React, { Fragment, useState, useRef } from "react";
...

const Upload = () => {
  const [weight, setWeight] = useState("");

  const imageUploadFrontRef = useRef();
  const imageUploadSideRef = useRef();
  const imageUploadBackRef = useRef();

  const [uploadErrors, setUploadErrors] = useState([{}]);

  const upload  = (e) => {
    e.preventDefault();
    
    const imageFront = imageUploadFrontRef.current.getImage();
    const imageSide = imageUploadSideRef.current.getImage();
    const imageBack = imageUploadBackRef.current.getImage();

    // do with the images what you need.
  }

  return (
    <Fragment>
      <Container>
        <FormWrap>
          <FormContent>
            <Form onSubmit={upload}>
              ...
              <PhotoWrap>
                <ImageUpload ref={imageUploadFrontRef} {...frontPhotoText} />
                <ImageUpload ref={imageUploadSideRef} {...sidePhotoText} />
                <ImageUpload ref={imageUploadBackRef} {...backPhotoText} />
              </PhotoWrap>
              ...
            </Form>
          </FormContent>
        </FormWrap>
      </Container>
    </Fragment>
  );
};
于 2021-07-16T08:32:02.610 回答