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