reactjs - 如何在 React 中访问子 useState?

标签 reactjs react-hooks frontend react-forwardref

我正在尝试在 React 中制作一个表单,其中包含用于上传图像的子组件(以进行预览并使其更美观),但问题是我无法访问图像在哪里的子组件的 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;

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

最佳答案

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

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

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>
  );
};

关于reactjs - 如何在 React 中访问子 useState?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68405489/

相关文章:

javascript - 如何使文本在另一个 div 内动态更改宽度的 div 上居中?

javascript - Redux useSelector 过滤对象?

reactjs - React hooks,每个 child 一个

javascript - 无法对对象数组使用数组方法

Angular:如何重置 matChipList 输入字段和 Google Recaptcha?

javascript - Angular JS,工厂返回数据,但在 Controller 中它消失了

javascript - 我应该如何处理 React 的 componentWillUnmount 中的离开动画?

reactjs - React-Leaflet 在 map 上绘制圆形标记

reactjs - 类型 'number' 不可分配给类型 'SetStateAction<undefined>' 。 - react

css - 带有搜索框的导航栏 - MaterializeCss