Next.js 13 /app目录下使用FileReader报ReferenceError问题排查
问题原因及修复方案
核心问题
虽然你加了"use client"标记,但组件顶层的const fileReader = new FileReader()会在Next.js的服务端预渲染阶段被执行,而FileReader是浏览器专属API,服务端环境不存在这个对象,所以抛出ReferenceError: FileReader is not defined。
另外代码还有两个潜在问题:
readAsText是异步操作,不会直接返回读取的文本内容,需要通过监听事件获取结果- 代码中
filename变量未定义,会导致后续路由跳转失败
修复后的代码
"use client"; import React, { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import useStore from "../app/store"; export default function FileUploader() { const [files, setFiles] = useState([]); const router = useRouter(); const addFile = useStore((state) => state.addFile); const onFileSelect = (event) => { event.preventDefault(); setFiles(event.target.files); }; useEffect(() => { if (!files[0]) return; // 仅在浏览器环境创建FileReader实例 const fileReader = new FileReader(); const filename = files[0].name; // 通过onload事件获取异步读取的结果 fileReader.onload = function(e) { const fileContent = e.target.result; addFile(fileContent); router.push(`/file/${filename}`); }; // 开始读取文件 fileReader.readAsText(files[0]); // 清理函数:避免组件卸载后触发事件 return () => { fileReader.abort(); }; }, [files, addFile, router]); return ( <input id="dropzone-file" type="file" className="fileInput" onChange={onFileSelect} /> ); }
关键修改点
- 把
FileReader实例的创建移到useEffect内部,确保只在浏览器客户端执行 - 使用
fileReader.onload事件监听读取完成,获取文件内容 - 补充
filename变量的定义(从选中文件的name属性获取) - 添加清理函数,在组件卸载时终止文件读取,避免内存泄漏
内容的提问来源于stack exchange,提问作者Cerix
相关产品推荐
相关产品推荐

