Javascript 如何解决Redux表单图像上传和裁剪问题?

Javascript 如何解决Redux表单图像上传和裁剪问题?,javascript,reactjs,redux,redux-form,Javascript,Reactjs,Redux,Redux Form,我在分页时在页面上呈现了一个用户列表。单击“编辑”按钮可以更改每个用户配置文件。模式有一个图像选择和上传,然后裁剪选项。图像选择、裁剪和上传工作正常,但问题是如果我选择了一个图像,然后关闭模式,然后转到下一个用户,它会显示相同的图像进行裁剪,而无需按下选择按钮。第二个问题与第一个有关,上传后的图像。选择任何要编辑的用户都会显示相同的图片 页面:UserUpdateModal.js: <AccountProfileForm submitCb={this.updateProfi

我在分页时在页面上呈现了一个用户列表。单击“编辑”按钮可以更改每个用户配置文件。模式有一个图像选择和上传,然后裁剪选项。图像选择、裁剪和上传工作正常,但问题是如果我选择了一个图像,然后关闭模式,然后转到下一个用户,它会显示相同的图像进行裁剪,而无需按下选择按钮。第二个问题与第一个有关,上传后的图像。选择任何要编辑的用户都会显示相同的图片

页面:UserUpdateModal.js:

<AccountProfileForm  
      submitCb={this.updateProfile} 
      errors={errors}
      options={this.options}
      initialValues ={this.props.initialValues}
      randomId={this.randomId()}
 />

页面AccountProfileForm.js

<Field
    name="first_name"
    type="text"
    label='First Name'
    className='form-control'
    component={BwmInput}
    validate={[required,text,minLength2, maxLength32]}
/>

<Field
    name="image_link"
    id={id}
    type="file"
    label='Image'
    className='form-control'
    component={BwmFileUpload}
/>

以下是要上载的主要类: BwmFileUpload.js

import React from 'react';
import ReactCrop, { makeAspectCrop } from 'react-image-crop';
import { toast } from 'react-toastify';
import * as actions from '../../../actions';
import { v4 as uuidv4 } from 'uuid';

export class BwmFileUpload extends React.Component {

 constructor() {
  super();

  this.state = {
  src: null,
  selectedFile: undefined,
  imageBase64: '',
  initialImageBase64: '',
  croppedImageUrl: {},
  blob:{},
  pending: false,
  status: 'INIT',
  crop: {
    unit: '%',
    width: 50,
    aspect: 3 / 4,
  }
 }
}

imageId=() =>{
 let id = Math.floor(Math.random() * 100) + 1;
 return id;
}

resetToDefaultState(status) {
 this.setState({
  pending: false,
  status,
  selectedFile: undefined,
  croppedImage: {},
  crop: {},
  initialImageBase64: '',
  imageBase64: ''
 });
}

onSelectFile = e => {
 const selectedFile = e.target.files[0];
 if (e.target.files && e.target.files.length > 0) {
   const reader = new FileReader();
   reader.addEventListener('load', () =>
    this.setState({ src: reader.result,selectedFile })
  );
  reader.readAsDataURL(selectedFile);
 }
};

onCropChange=(crop) =>{
 this.setState({ crop });
}

onImageLoaded = image => {
 this.imageRef = image;
 if (image.naturalWidth > 1920 && image.naturalHeight > 1080) {

  this.resetToDefaultState('INIT');
  toast.error('Max width of an image is 1920px and height 1080px');
  return;
 }
}

onCropComplete = crop => {
this.makeClientCrop(crop);
};
async makeClientCrop(crop) {
 const { selectedFile } = this.state;
 if (this.imageRef && crop.width && crop.height) {
  const croppedImageUrl = await this.getCroppedImg(this.imageRef, crop, selectedFile.name);
  this.setState({ croppedImageUrl });
 }
}


getCroppedImg(image, crop, fileName) {
 const canvas = document.createElement('canvas');
 const scaleX = image.naturalWidth / image.width;
 const scaleY = image.naturalHeight / image.height;
 canvas.width = crop.width;
 canvas.height = crop.height;
 const ctx = canvas.getContext('2d');
 ctx.drawImage(
  image,
  crop.x * scaleX,
  crop.y * scaleY,
  crop.width * scaleX,
  crop.height * scaleY,
  0,
  0,
  crop.width,
  crop.height
 );

return new Promise((resolve, reject) => {
  canvas.toBlob(blob => {
    if (!blob) {
      //reject(new Error('Canvas is empty'));
      toast.error('Canvas is empty');
      return;
    }
    blob.name = fileName;
    this.setState({blob});
    window.URL.revokeObjectURL(this.fileUrl);
    this.fileUrl = window.URL.createObjectURL(blob);
    resolve(this.fileUrl);
  }, 'image/jpeg');
 });
}

onError=(error)=> {
 this.setState({pending: false, status: 'FAIL'});
}

onSuccess = (uploadedImage) => {
 const {onChange} = this.props.input || this.props;
 this.resetToDefaultState('INIT');
 onChange(uploadedImage);
 this.setState({src: null,selectedFile:undefined});
}

uploadImage=()=> {
 const { blob } = this.state;
 if (blob) {
  this.setState({pending: true, status: 'INIT'});
  actions.uploadImage(blob, 'users').then(
    (uploadedImage) => { this.onSuccess(uploadedImage) },
    (error) => { this.onError(error)})
 }
}

renderSpinningCircle() {
 const { pending } = this.state;
 if (pending) {
   return (
    <div className='img-loading-overlay'>
      <div className='img-spinning-circle'>
      </div>
    </div>
    )
  }
}

renderImageStatus() {
 const { status } = this.state;
 if (status === 'OK') {
  return <div className='alert alert-success'> Image Uploaded Succesfuly! </div>
}

if (status === 'FAIL') {
  return <div className='alert alert-danger'> Image Upload Failed! </div>
 }
}

render() {
  const {crop,croppedImageUrl, src  } = this.state;
  return (
    <div className='img-upload-container' id={this.imageId()}>
    <label className='img-upload btn btn-bwm'>
     <span className='upload-text'> Select an image </span>
     <input type='file' id={this.imageId()}
            accept='.jpg, .png, .jpeg'
            onChange={this.onSelectFile}/>
    </label>

    { src &&
      <button className='btn btn-success btn-upload'
              type='button' id={this.imageId()}
              disabled={!src}
              onClick={() => this.uploadImage()}>
          Upload Image
      </button>
    }

    { src &&
      <ReactCrop src={src}
                 crop={crop}
                 ruleOfThirds
                 onImageLoaded={this.onImageLoaded}
                 onComplete={this.onCropComplete}
                 onChange={this.onCropChange} />
    }

    { croppedImageUrl &&
      <div className='img-preview-container'  id={this.imageId()}>
        <div className='img-preview' id={this.imageId()}
             style={{'backgroundImage': 'url(' + croppedImageUrl + ')'}}>
        </div>
      
        {this.renderSpinningCircle()}
      </div>
    }

    {this.renderImageStatus()}
  </div>
 )
 }
}
从“React”导入React;
从“react image crop”导入ReactCrop,{makeAspectCrop};
从'react toastify'导入{toast};
从“../../../actions”导入*作为操作;
从“uuid”导入{v4作为uuidv4};
导出类BwmFileUpload扩展了React.Component{
构造函数(){
超级();
此.state={
src:null,
selectedFile:未定义,
imageBase64:“”,
initialImageBase64:“”,
croppedImageUrl:{},
水滴:{},
待定:错误,
状态:“INIT”,
作物:{
单位:‘’,
宽度:50,
相位:3/4,
}
}
}
imageId=()=>{
设id=Math.floor(Math.random()*100)+1;
返回id;
}
重置默认状态(状态){
这是我的国家({
待定:错误,
地位
selectedFile:未定义,
裁剪图像:{},
作物:{},
initialImageBase64:“”,
imageBase64:“”
});
}
onSelectFile=e=>{
const selectedFile=e.target.files[0];
如果(e.target.files&&e.target.files.length>0){
const reader=new FileReader();
reader.addEventListener('load',()=>
this.setState({src:reader.result,selectedFile})
);
reader.readAsDataURL(selectedFile);
}
};
onCropChange=(裁剪)=>{
这个.setState({crop});
}
onImageLoaded=图像=>{
this.imageRef=图像;
if(image.naturalWidth>1920&&image.naturalHeight>1080){
resetToDefaultState('INIT');
toast.error('图像的最大宽度为1920px,高度为1080px');
返回;
}
}
onCropComplete=裁剪=>{
这个.makeClientCrop(crop);
};
异步makeClientCrop(裁剪){
const{selectedFile}=this.state;
if(this.imageRef&&crop.width&&crop.height){
const cropedimagerurl=wait this.getcropedimg(this.imageRef,crop,selectedFile.name);
this.setState({cropedimageurl});
}
}
getCroppedImg(图像、裁剪、文件名){
const canvas=document.createElement('canvas');
const scaleX=image.naturalWidth/image.width;
const scaleY=image.naturalHeight/image.height;
canvas.width=crop.width;
canvas.height=crop.height;
const ctx=canvas.getContext('2d');
ctx.drawImage(
形象,,
crop.x*scaleX,
crop.y*scaleY,
crop.width*scaleX,
crop.height*scaleY,
0,
0,
裁剪宽度,
作物高度
);
返回新承诺((解决、拒绝)=>{
canvas.toBlob(blob=>{
如果(!blob){
//拒绝(新错误(“画布为空”);
toast.error('Canvas为空');
返回;
}
blob.name=文件名;
this.setState({blob});
window.URL.revokeObjectURL(this.fileUrl);
this.fileUrl=window.URL.createObjectURL(blob);
解析(this.fileUrl);
}“图像/jpeg”);
});
}
onError=(错误)=>{
this.setState({pending:false,status:'FAIL'});
}
onSuccess=(上传图像)=>{
const{onChange}=this.props.input | | this.props;
resetToDefaultState('INIT');
onChange(上传图像);
this.setState({src:null,selectedFile:undefined});
}
上传图像=()=>{
const{blob}=this.state;
如果(blob){
this.setState({pending:true,status:'INIT'});
uploadImage(blob,'users')。然后(
(UploadeImage)=>{this.onSuccess(UploadeImage)},
(错误)=>{this.onError(错误)})
}
}
RenderSpiningCircle(){
const{pending}=this.state;
如果(待定){
返回(
)
}
}
renderImageStatus(){
const{status}=this.state;
如果(状态=='OK'){
返回图片上传成功!
}
如果(状态==‘失败’){
返回图像上传失败!
}
}
render(){
const{crop,cropeImage URL,src}=this.state;
返回(
选择一个图像
{src&&
this.uploadImage()}>
上传图像
}
{src&&
}
{裁剪图像URL&&
{this.renderSpiningCircle()}
}
{this.renderImageStatus()}
)
}
}