Как реализовать виджет загрузки Cloudinary в React?

#javascript #reactjs #file-upload #cloudinary

#javascript #reactjs #загрузка файла #cloudinary

Вопрос:

Я пытаюсь использовать виджет загрузки Cloudinary в своем приложении React, но у меня проблема. При запуске проекта виджет загрузки появляется немедленно, но при закрытии и повторном открытии приложение завершает работу и отображает следующее сообщение:

widget.open() не является функцией

Примечание: Загрузка работает корректно

 import React, { Component } from 'react';
import './App.css';

class App extends Component {
  showWidget = (widget) => {
    widget.open();
  }

  checkUploadResult = (resultEvent) => {
    if(resultEvent.event === 'success'){
      console.log(resultEvent)
    }
  }
  render() {
      let widget = window.cloudinary.openUploadWidget({
      cloudName: "*********",
      uploadPreset: "tryingfirsttime"},
      (error, result) => {this.checkUploadResult(result)});

    return (
      <div className="App">
        <button onClick={this.showWidget}> Upload file</button>
      </div>
    );
  }
}

export default App;  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<script src="https://widget.cloudinary.com/v2.0/global/all.js" type="text/javascript"></script>   

введите описание изображения здесь

введите описание изображения здесь

Ответ №1:

Во-первых, давайте разберемся в проблеме. Виджет загрузки Cloudinary определен в функции рендеринга компонента, и когда этот компонент будет рендерен, он откроет виджет загрузки, поскольку он определен с функциональностью openUploadWidget . Во-вторых, виджет определен только в области действия функции визуализации и недоступен за ее пределами, отсюда и ошибка widget.open() is not a function .

Чтобы устранить эти проблемы, я бы сначала начал с определения виджета либо как локальной переменной, либо как части состояния. Это делается путем включения конструктора в состав вашего компонента:

 constructor(props) {
   super(props)

   // Defined in state
   this.state = { . . . }

   // Defined as local variable
   this.widget = myLocalVariable
}
  

Следующее, что нужно сделать, это при создании экземпляра виджета загрузки Cloudinary использовать, createUploadWidget а не openUploadWidget нет, чтобы разрешить контроль над тем, когда открывать виджет.

 constructor(props) {
   super(props)
   // Defined in state
   this.state = {
      widget: cloudinary.createUploadWidget({
         cloudName: 'my_cloud_name', 
         uploadPreset: 'my_preset'}, 
         (error, result) => { 
            if (!error amp;amp; result amp;amp; result.event === "success") { 
               console.log('Done! Here is the image info: ', result.info); 
            }
         }
      })
    }
    // Defined as local variable
    this.widget = cloudinary.createUploadWidget({
       cloudName: 'my_cloud_name', 
       uploadPreset: 'my_preset'}, (error, result) => { 
         if (!error amp;amp; result amp;amp; result.event === "success") { 
           console.log('Done! Here is the image info: ', result.info); 
         }
       }
    })
 }
  

Наконец, событию showWidget click не нужен виджет, передаваемый в качестве аргумента (поскольку он определен локально в компоненте), и на него также можно ссылаться с помощью this ключевого слова. Обратите внимание, что вам нужно будет включить ключевое слово this для ссылки на текущий компонент.

 showWidget = () => {
  this.widget.open();
}
  

Я включил JSFiddle, показывающий конечный результат:
https://jsfiddle.net/danielmendoza/fve1kL53 /

Ответ №2:

Я добавлю, что вам, возможно, потребуется переписать функцию showWidget, чтобы предотвратить событие по умолчанию, если вы пытаетесь установить состояние с помощью результата URL. В противном случае вы получите сообщение об ошибке, что вы не можете использовать setState () в размонтированном компоненте.

 showWidget = (e) => {
  e.preventDefault();
  this.widget.open();
}