使用react-image-file-resizer时出现读取未定义属性错误求助
排查react-image-file-resizer的"Cannot read properties of undefined"错误
问题描述
使用react-image-file-resizer包处理input上传的图片时,触发"Cannot read properties of undefined"错误,以下是相关代码、环境信息及错误截图,请求排查原因和解决办法。
相关代码
create.js
import { useState, useEffect } from "react"; import axios from "axios"; import InstructorRoute from "../../../components/routes/InstructorRoute"; import CourseCreateForm from "../../../components/forms/CourseCreateForm"; import {Resizer} from "react-image-file-resizer"; import { toast } from "react-toastify"; const CourseCreate = () => { // state const [values, setValues] = useState({ name: "", description: "", price: "9.99", uploading: false, paid: true, category: "", loading: false, }); const [image, setImage] = useState({}); const [preview, setPreview] = useState(""); const [uploadButtonText, setUploadButtonText] = useState("Upload Image"); const handleChange = (e) => { setValues({ ...values, [e.target.name]: e.target.value }); }; const handleImage = (e) => { let file = e.target.files[0]; setPreview(window.URL.createObjectURL(file)); setUploadButtonText(file.name); setValues({ ...values, loading: true }); // resize Resizer.imageFileResizer(file, 720, 500, "JPEG", 100, 0, async (uri) => { try { let { data } = await axios.post("/api/course/upload-image", { image: uri, }); console.log("IMAGE UPLOADED", data); // set image in the state setImage(data); setValues({ ...values, loading: false }); } catch (err) { console.log(err); setValues({ ...values, loading: false }); toast("Image upload failed. Try later."); } }); }; const handleImageRemove = async () => { try { // console.log(values); setValues({ ...values, loading: true }); const res = await axios.post("/api/course/remove-image", { image }); setImage({}); setPreview(""); setUploadButtonText("Upload Image"); setValues({ ...values, loading: false }); } catch (err) { console.log(err); setValues({ ...values, loading: false }); toast("Image upload failed. Try later."); } }; const handleSubmit = async (e) => { e.preventDefault(); console.log(values); }; return ( <InstructorRoute> <h1 className="jumbotron text-center square">Create Course</h1> <div className="pt-3 pb-3"> <CourseCreateForm handleSubmit={handleSubmit} handleImage={handleImage} handleChange={handleChange} values={values} setValues={setValues} preview={preview} uploadButtonText={uploadButtonText} handleImageRemove={handleImageRemove} /> </div> <pre>{JSON.stringify(values, null, 4)}</pre> <hr /> <pre>{JSON.stringify(image, null, 4)}</pre> </InstructorRoute> ); }; export default CourseCreate;
CourseCreateForm组件
import { Select, Button, Avatar } from "antd"; const { Option } = Select; const CourseCreateForm = ({ handleSubmit, handleImage, handleChange, values, setValues, preview, uploadButtonText, }) => { const children = []; for (let i = 9.99; i <= 100.99; i++) { children.push(<Option key={i.toFixed(2)}>${i.toFixed(2)}</Option>); } return ( <form onSubmit={handleSubmit}> <div className="form-group"> <input type="text" name="name" className="form-control" placeholder="Name" value={values.name} onChange={handleChange} /> </div> <div className="form-group"> <textarea name="description" cols="7" rows="7" value={values.description} className="form-control" onChange={handleChange} ></textarea> </div> <div className="form-row"> <div className="col"> <div className="form-group"> <Select style={{ width: "100%" }} size="large" value={values.paid} onChange={(v) => setValues({ ...values, paid: !values.paid })} > <Option value={true}>Paid</Option> <Option value={false}>Free</Option> </Select> </div> </div> {values.paid && ( <div className="form-group"> <Select defaultValue="$9.99" style={{ widht: "100%" }} onChange={(v) => setValues({ ...values, price: v })} tokenSeparators={[,]} size="large" > {children} </Select> </div> )} </div> <div className="form-group"> <input type="text" name="category" className="form-control" placeholder="Category" value={values.category} onChange={handleChange} /> </div> <div className="form-row"> <div className="col"> <div className="form-group"> <label className="btn btn-outline-secondary btn-block text-left"> {uploadButtonText} <input type="file" name="image" onChange={handleImage} accept="image/*" hidden /> </label> </div> </div> {preview && ( <Avatar width={200} src={preview}> </Avatar> )} </div> <div className="row"> <div className="col"> <Button onClick={handleSubmit} disabled={values.loading || values.uploading} className="btn btn-primary" loading={values.loading} type="primary" size="large" shape="round" > {values.loading ? "Saving..." : "Save & Continue"} </Button> </div> </div> </form> ); }; export default CourseCreateForm;
错误截图

环境版本
- react-image-file-resizer:0.4.7、0.4.2、0.4.8
- npm:8.19.2
- node:18.12.1
原因分析
从错误截图和代码来看,核心问题是**Resizer对象为undefined**,导致调用Resizer.imageFileResizer时触发"Cannot read properties of undefined"错误。
react-image-file-resizer 0.4.x版本采用默认导出而非命名导出,当前使用的import {Resizer} from "react-image-file-resizer";属于错误的导入方式,无法正确获取到Resizer对象。
解决办法
- 修正导入语句
将create.js中的导入代码改为默认导入:
import Resizer from "react-image-file-resizer";
保持后续Resizer.imageFileResizer的调用逻辑不变即可。
- 验证依赖安装
如果修改导入后仍有问题,可重新安装依赖包确保版本正确:
npm uninstall react-image-file-resizer npm install react-image-file-resizer@0.4.8
- 额外边界检查(可选)
为避免用户未选择文件就触发逻辑,可在handleImage函数中添加文件存在性判断:
const handleImage = (e) => { let file = e.target.files?.[0]; if (!file) return; // 无文件时直接返回 // 后续原有逻辑... };
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

