在React-Cropper实现图片裁剪的使用中 在使用这段代码的时候 报错
解决方法一:
查看你的 react-cropper版本 我这里的版本是
你可以将 react-cropper的版本降到 "react-cropper": "^1.2.0" 1.*的版本即可
解决方法二(推荐):
按照官方的解释,2.*版本开始弃用ref 的形式 而使用 onInitialized
附上组件代码供参考
import React ,{Component} from 'react'
import request from "umi-request";
import './index.less'
import Cropper from 'react-cropper' // 引入Cropper
import 'cropperjs/dist/cropper.css' // 引入Cropper对应的css
import { Button } from 'antd';
import {dataURLtoFile} from '@/utils'
import {uploadCropperImg} from '@/api'
interface CropperImgProps {
uploadedImageFile:any
onClose:Function
onSubmit:Function
}
interface CropperImgState {
src:string,
submitting:boolean
}
class CropperImg extends Component<CropperImgProps, CropperImgState>{
state = {
src:'',
submitting:false
}
cropper: any
componentDidMount() {
const fileReader = new FileReader()
fileReader.onload =(e:any) => {
const dataURL = e.target.result
console.log(e)
this.setState({ src: dataURL })
}
fileReader.readAsDataURL(this.props.uploadedImageFile)
}
handleSubmit = () => {
if (!this.state.submitting) {
let dataurl = this.cropper.getCroppedCanvas().toDataURL()
let formData = new FormData()
let newFile = dataURLtoFile(dataurl,this.props.uploadedImageFile.name)
formData.append('file', newFile)
uploadCropperImg(formData).then(res => {
console.log('res====',res)
if(res.code == 200){
console.log(res.data)
this.props.onSubmit(res.data)
}
})
}
this.props.onClose()
}
onCropperInit=(cropper:any) => { this.cropper = cropper }
render() {
return (
<div className="class-cropper-modal">
<div className="modal-panel">
<div className="cropper-container-container">
<div className="cropper-container">
<Cropper
src={this.state.src}
className="cropper"
// ref={cropper => (this.cropper = cropper)}
// Cropper.js options
onInitialized={this.onCropperInit.bind(this)}
viewMode={1}
zoomable={true}
aspectRatio={1} // 固定为1:1 可以自己设置比例, 默认情况为自由比例
guides={false}
preview=".cropper-preview"
/>
</div>
<div className="preview-container">
<div className="cropper-preview" />
</div>
</div>
<div className="button-row">
<Button type="primary" onClick={this.handleSubmit}>点击提交</Button>
<Button style={{ marginLeft: '100px' }} onClick={() => this.props.onClose()}>取消</Button>
{/*<div className="submit-button" onClick={this.handleSubmit}>*/}
{/* 点击提交*/}
{/*</div>*/}
</div>
</div>
</div>
)
}
}
export default CropperImg
补充:父组件代码
import React, { Component, useState } from 'react';
import { Tabs, Modal, Button, Input, Radio, message, Select,DatePicker, Space } from 'antd';
import styles from './index.less';
import moment from 'moment'
import { AppStoreProps } from '@/store/appStore';
import { inject, observer } from 'mobx-react';
import CropperImg from '@/components/CropperImg';
import {updateUserInfo} from '@/api'
import userMessageStore, { UserMessageStoreProps } from '@/pages/UserCenter/UserMessage/store';
import { FormOutlined } from '@ant-design/icons';
const { TabPane } = Tabs;
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 文件最大限制为5M
const { Option } = Select;
const dateFormat = 'YYYY-MM-DD'
function callback(key: string) {
console.log(key);
}
interface UserMessageProps {
appStore: AppStoreProps
userMessageStore: UserMessageStoreProps
}
interface UserMessageState {
isShowCopper: boolean
classModalFile: any
classModalVisible: boolean
classResultImgUrl: String
isChange:Boolean, //是否编辑
// account,education,name,degree,gender,email,userBirthday,idCard
account:String,
education:String,
name:String,
degree:String,
gender:Number,
email:String,
userBirthday:String,
idCard:String
}
@inject('appStore', 'userMessageStore') @observer
export default class UserMessage extends Component<UserMessageProps, UserMessageState> {
state = {
isShowCopper: false,
classModalFile: null,
classModalVisible: false,
classResultImgUrl: this.props.appStore.userInfo.iconUrl,
isChange:true,
account:this.props.appStore.userInfo.account,
education:this.props.appStore.userInfo.education,
name:this.props.appStore.userInfo.name,
degree:this.props.appStore.userInfo.degree,
gender:this.props.appStore.userInfo.gender,
email:this.props.appStore.userInfo.email,
userBirthday:this.props.appStore.userInfo.userBirthday,
idCard:this.props.appStore.userInfo.idCard
};
fileInputEl = React.createRef();
componentDidMount() {
console.log(this.props.appStore.userInfo, '个人信息');
}
upLoadImg = () => {
this.props.userMessageStore.imgCopperFun();
this.setState({
isShowCopper: this.props.userMessageStore.isShowCopper,
});
};
handleGetResultImgUrl = (key: string) => (url: string) => {
const str = url;
// @ts-ignore
this.setState({
[key]: str,
},() => {
this.saveUserInfo()
});
};
handleClassFileChange = (e: any) => {
const file = e.target.files[0];
console.log(file,'file')
if (file) {
if (file.size <= MAX_FILE_SIZE) {
this.setState(
{
classModalFile: file, // 先把上传的文件暂存在state中
},
() => {
this.setState({
classModalVisible: true, // 然后弹出modal
});
},
);
} else {
message.warning('文件过大');
}
}
};
changeGender = (e: any) => {
this.setState({
gender: e.target.value,
});
};
selectEducation = (value: string) => {
this.setState({
education:value
})
};
selectDate = (date:any, dateString:string) => {
this.setState({
userBirthday:dateString
})
}
selectAcademic = (value:string) => {
this.setState({
degree:value
})
}
changeUserInfo =() => {
this.setState({
isChange:false
})
}
cancelChangeUserInfo = () => {
this.setState({
isChange:true
})
}
changeAccount = (e:any) => {
this.setState({
account:e.target.value
})
}
saveUserInfo = () => {
let data = {
"education": this.state.education, //学历
"gender": this.state.education, //性别(1男,2女)
"degree": this.state.degree,//学位
"name": this.state.name,//姓名
"iconUrl": process.env.VUE_APP_DOWN_API + this.state.classResultImgUrl,//头像
"email": this.state.email,//邮箱
"userBirthday": this.state.userBirthday, //生日
"idCard": this.state.idCard,//身份证号,
"nation": "汉族",//民族
"politicCountenance": "中共党员", //政治面貌
"graduateSchool": "辽宁沈阳农业大学", //毕业院校
}
console.log(data)
}
changeEmail = (e:any) => {
this.setState({
email:e.target.value
})
}
changeName = (e:any) => {
this.setState({
name:e.target.value
})
}
changeIdCard = (e:any) => {
this.setState({
idCard:e.target.value
})
}
render() {
const { isShowCopper, classModalFile, classResultImgUrl, classModalVisible,isChange,account,education,name,degree,gender,email,userBirthday,idCard } = this.state;
return (
<div id="usermessage" className={styles.usermessage}>
<Tabs defaultActiveKey="1" onChange={callback}>
<TabPane tab="个人资料" key="1" style={{position:'relative'}}>
<div>
<span>头像:</span>
<img className={styles.userimg} src={classResultImgUrl} alt=""/>
<div className={styles.half_area}>
<label className="upload-input-label">
<Button type="primary" onClick={() =>
// @ts-ignore
this.fileInputEl.current.click()}>上传图片</Button>
<input
type="file"
hidden
// @ts-ignore
ref={this.fileInputEl}
accept="image/jpeg,image/jpg,image/png"
className="base-upload-input"
onChange={this.handleClassFileChange}
/>
</label>
</div>
</div>
<div className={styles.formOutStyle} onClick={this.changeUserInfo}><FormOutlined /></div>
<div className={styles.flexBetween}>
<div className={styles.flexAlignItems}>
用户名:<div>{account}</div>
</div>
<div className={styles.flexAlignItems}>
性别:<Radio.Group disabled={isChange} value={gender} onChange={this.changeGender} style={{marginLeft:'27px' }}>
<Radio value={1}>男</Radio>
<Radio value={2}>女</Radio>
</Radio.Group>
</div>
</div>
<div className={styles.flexBetween}>
<div className={styles.flexAlignItems}>
学历:
<Select defaultValue={education} disabled={isChange} style={{ width: 200,marginLeft:'13px' }} onChange={this.selectEducation}>
<Option value="专科">专科</Option>
<Option value="本科">本科</Option>
<Option value="硕士研究生">硕士研究生</Option>
</Select>
</div>
<div className={styles.flexAlignItems}>
邮箱:<Input placeholder="请输入邮箱" disabled={isChange} onChange={this.changeEmail} value={email} style={{ width: '200px',marginLeft:'27px' }}/>
</div>
</div>
<div className={styles.flexBetween}>
<div className={styles.flexAlignItems}>
姓名:<Input placeholder="请输入用户姓名" disabled={isChange} onChange={this.changeName} value={name} style={{ width: '200px',marginLeft:'13px' }}/>
</div>
<div className={styles.flexAlignItems}>
出生日期:<Space direction="vertical" >
<DatePicker disabled={isChange} defaultValue={moment(userBirthday, dateFormat)} format={dateFormat} onChange={this.selectDate} />
</Space>
</div>
</div>
<div className={styles.flexBetween}>
<div className={styles.flexAlignItems}>
学位:
<Select style={{ width: 200 ,marginLeft:'13px'}} disabled={isChange} defaultValue={degree} onChange={this.selectAcademic}>
<Option value="博士">博士</Option>
<Option value="硕士">硕士</Option>
<Option value="学士">学士</Option>
</Select>
</div>
<div className={styles.flexAlignItems}>
身份证号:<Input placeholder="请输入身份证号" disabled={isChange} onChange={this.changeIdCard} value={idCard} style={{ width: '200px' }}/>
</div>
</div>
{
!isChange?
<div style={{textAlign:'center'}}>
<Button onClick={this.cancelChangeUserInfo}>取消</Button>
<Button type="primary" onClick={this.saveUserInfo} style={{marginTop:'100px',marginLeft:'100px'}}>保存</Button>
</div>
:
''
}
</TabPane>
<TabPane tab="职业信息" key="2">
Content of Tab Pane 2
</TabPane>
</Tabs>
{classModalVisible && (<CropperImg uploadedImageFile={classModalFile}
onClose={() => {
this.setState({ classModalVisible: false });
}}
onSubmit={this.handleGetResultImgUrl('classResultImgUrl')}/>)}
</div>
);
}
}