Reactjs приложение не показывает предварительный просмотр изображения в сафари - PullRequest
0 голосов
/ 18 января 2020

Я пытаюсь создать приложение, в котором пользователь может загрузить изображение и отправить его по электронной почте, оно отлично работает во всех браузерах, кроме Safari. Как для мобильного, так и для веб-браузеров, когда я выбираю изображение для загрузки, кажется, что ничего не просматривается и не загружается (готово к отправке). Что я могу сделать, чтобы это исправить? Мой код в его нынешнем виде очень прост:

const EnterDetailPage = props => {
  const [imageUrl, setImageUrl] = useState("");
  const [imageFile, setImageFile] = useState();
  const [upload, setUpload] = useState(null);
const handleUploadChange = async e => {
    setLoading(true);
    const file = e.target.files[0];
    if (!file) {
      return;
    }
    setUpload(URL.createObjectURL(file));
    setImageFile(file);
    const ref = firebase
      .storage()
      .ref()
      .child(uuid.v4());

    const snapshot = await ref.put(file);
    let getImageUrl = await snapshot.ref.getDownloadURL();
    setImageUrl(getImageUrl);
    setLoading(false);
    console.log(getImageUrl);
  };
  let imgPreview = null;
    if (upload) {
    imgPreview = (
      <Avatar
        variant="square"
        src={upload}
        alt="Avatar"
        className={classes.bigAvatar}
      />
    );
  }
  return(
<div className="m-auto p-16 sm:px-24 sm:mx-auto max-w-xl">
        <input
          accept="image/jpeg,image/gif,image/png"
          className="hidden"
          id="button-file"
          type="file"
          // onChange={handleUploadChange}
          onInput={handleUploadChange}
          onClick={event => {
            event.target.value = null;
          }}
        />
        <label
          htmlFor="button-file"
          className={`${classes.bigAvatar} mt-8 bg-gray-300 m-auto flex items-center justify-center relative w-128 h-128 rounded-4 a-mr-16 a-mb-16 overflow-hidden cursor-pointer shadow-1 hover:shadow-xl`}
        >
          <div className="absolute flex items-center justify-center w-full h-full z-50">
          {imageUrl ? null :
            <Icon fontSize="large" color="primary" className="cloud-icon">
              cloud_upload
            </Icon>}
          </div>
          {imgPreview}
        </label>
);
}:

Я сравнил свой код с этой статьей здесь: https://w3path.com/react-image-upload-or-file-upload-with-preview/

и похоже, что я сделал точно так же ... почему я не получаю такие же результаты?

1 Ответ

2 голосов
/ 21 января 2020

Пример вашего кода и ящика идет довольно далеко, но, разобрав его на части, я смог отследить проблему ...

Кажется, Safari не поддерживает input элементы которые пытаются использовать прослушиватель событий onInput - обратный вызов никогда не выполняется. Вместо этого вы можете использовать прослушиватель событий onChange.


. В приведенном ниже примере я фальсифицировал вызов API, установив Promise с таймаутом, но это не нужно и предназначено только для демонстрации. цели. Кроме того, мне нравится использовать объекты в нескольких отдельных состояниях, особенно когда состояние должно быть синхронным - оно также чище, легче для чтения и функционирует больше как компонент на основе class.

Демо : https://jd13t.csb.app/

Источник :

Edit Image Upload Preview


компонентов / DetailPage. js

import React, { useRef, useState } from "react";
import { CircularProgress, Icon, Fab } from "@material-ui/core";

const initialState = {
  isLoading: false,
  imageName: "",
  imagePreview: null,
  imageSize: 0
};

const EnterDetailPage = () => {
  const [state, setState] = useState(initialState);
  const uploadInputEl = useRef(null);

  const handleUploadChange = async ({ target: { files } }) => {
    setState(prevState => ({ ...prevState, isLoading: true }));

    const file = files[0];
    await new Promise(res => {
      setTimeout(() => {
        res(
          setState(prevState => ({
            ...prevState,
            imageName: file.name,
            imagePreview: URL.createObjectURL(file),
            imageSize: file.size,
            isLoading: false
          }))
        );
      }, 2000);
    });
  };

  const resetUpload = () => {
    setState(initialState);
    uploadInputEl.current.value = null;
  };

  const uploadImage = async () => {
    if (state.imagePreview)
      setState(prevState => ({ ...prevState, isLoading: true }));

    await new Promise(res => {
      setTimeout(() => {
        res(alert(JSON.stringify(state, null, 4)));
        resetUpload();
      }, 2000);
    });
  };

  const { imagePreview, imageName, imageSize, isLoading } = state;

  return (
    <div style={{ padding: 20 }}>
      <div style={{ textAlign: "center" }}>
        <div>
          <input
            accept="image/jpeg,image/gif,image/png"
            className="hidden"
            id="button-file"
            type="file"
            ref={uploadInputEl}
            onChange={handleUploadChange}
          />
          <label htmlFor="button-file">
            <div>
              {imagePreview ? (
                <>
                  <img
                    src={imagePreview}
                    alt="Avatar"
                    style={{ margin: "0 auto", maxHeight: 150 }}
                  />
                  <p style={{ margin: "10px 0" }}>
                    ({imageName} - {(imageSize / 1024000).toFixed(2)}MB)
                  </p>
                </>
              ) : (
                <Icon fontSize="large" color="primary" className="cloud-icon">
                  cloud_upload
                </Icon>
              )}
            </div>
          </label>
          <Fab
            variant="extended"
            size="large"
            color="primary"
            aria-label="add"
            className=""
            type="button"
            onClick={uploadImage}
          >
            {isLoading ? (
              <CircularProgress style={{ color: "white" }} />
            ) : (
              "Submit"
            )}
          </Fab>
          {imagePreview && (
            <Fab
              variant="extended"
              size="large"
              color="default"
              aria-label="add"
              className=""
              type="button"
              onClick={resetUpload}
            >
              Cancel
            </Fab>
          )}
        </div>
      </div>
    </div>
  );
};

export default EnterDetailPage;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...