问题
I'm trying to use the Cloudinary Upload Widget in my React App but i have a problem. When running the project, the Upload Widget appears immediately, but when closed and opened again, the app crashes and displays the following message:
widget.open() is not a function
Note: The upload works correctly
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>
enter image description here
enter image description here
回答1:
First, let's understand the issue. The Cloudinary upload widget is defined in the render function of the component and when that component is rendered, it will open the upload widget since it's defined with the functionality of openUploadWidget
. Secondly, the widget is defined only in the scope of the render function and not accessible outside of it, hence the error widget.open() is not a function
.
To remedy these issues, I would first start by defining the widget either as a local variable or part of the state. This is done by including the constructor as part of your component:
constructor(props) {
super(props)
// Defined in state
this.state = { . . . }
// Defined as local variable
this.widget = myLocalVariable
}
The next thing to do is when creating an instance of the Cloudinary upload widget, to use createUploadWidget
and not openUploadWidget
, to allow control of when to open the widget.
constructor(props) {
super(props)
// Defined in state
this.state = {
widget: cloudinary.createUploadWidget({
cloudName: 'my_cloud_name',
uploadPreset: 'my_preset'},
(error, result) => {
if (!error && result && 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 && result && result.event === "success") {
console.log('Done! Here is the image info: ', result.info);
}
}
})
}
Lastly, the showWidget click event does not need the widget passed as an argument (since it's defined locally in the component) and can be referred too with the this
keyword. Note that you'll need to include the keyword this to refer to the current component.
showWidget = () => {
this.widget.open();
}
I have included a JSFiddle showing the end result: https://jsfiddle.net/danielmendoza/fve1kL53/
来源:https://stackoverflow.com/questions/55292306/how-to-implement-cloudinary-upload-widget-in-react