我正在尝试在React中实现文件读取器功能,但它在 reader.onload 部分抛出了“ TypeError:无法添加属性onload,对象不可扩展”的错误。有人可以帮忙弄清楚出什么问题吗?
handleFile = (file) => {
const reader = new FileReader();
reader.onload = (event) => {
const file = event.target.result;
const allLines = file.split(/\r\n|\n/);
// Reading line by line
allLines.forEach((line) => {
console.log(line);
});
};
reader.onerror = (event) => {
alert(event.target.error.name);
};
reader.readAsText(file);
}
这是我在类组件中返回的位:
<div className="upload">
<input
type="file"
id="file"
className="input-file"
accept=".txt"
onChange={(e) => this.handleFile(e.target.files[0]) }
/>
</div>
奇怪的是,代码本身可以独立工作,但不能在我的应用程序中工作。这是我的App.js:
import React, { Component } from 'react';
import './App.css';
import Layout from './components/Layout';
import Terminal from './containers/Terminal';
import Prompt from './components/Prompt'
import ChatLine from './components/ChatLine'
import Chat from './containers/Chat';
import FakeData from './components/FakeData';
import FileReader from './components/FileReader'
let optionCount = {
a: 0,
b: 0,
c: 0,
d: 0,
}
//////////////////////////////////////////////////////////////////
console.log("PLEASE FileReader.fakeDataFromReader", typeof FileReader)
class App extends Component {
// regulates the sequence, userinput
state = {
userInput: '',
userAnswer: '',
prevSeq: 'Landing',
currSeq: 'Landing',
nextSeq: '',
backontrackseq: 'Landing',
Landing: {
a: 'Info',
b: 'Upload',
},
Info: {
a: 'Upload',
},
Upload: {
done: 'Person',
},
Person: {
a: 'Ready',
b: 'Ready',
},
Ready: {
a: 'Talk',
b: 'Person',
},
Talk: {
restart: 'Landing',
},
Invalid: {
start: 'Landing',
back: ''
},
renderSeq: 'Landing',
chatContent: [
'I\'m here to talk.',
'Blueberry Placeholder',
'Sheme',
],
optionToRender: null,
};
componentDidMount() {
}
componentWillUnmount() {
}
inputChangedHandler = (event) => {
this.setState({userInput: event.target.value})
}
keyPressedHandler = (event) => {
let key = event.keyCode || event.which;
if (key === 13){
let userAnswer = event.target.value.toLowerCase();
this.setState({userAnswer:userAnswer})
// if currseq is chat, get optiontorender
if (this.state.currSeq === 'Talk' && userAnswer !== 'restart'){
let optionToRender = this.chatOptionHandler(userAnswer)
// this.setState({optionToRender: optionToRender})
// set state here!
let addToChatContent = this.updateChatContent(optionToRender) // this is a new chosen line to add
this.setState({
optionToRender: optionToRender,
chatContent: [...this.state.chatContent, addToChatContent]
})
} else { // otherwise render seq
let seqToRender = this.resHandler(userAnswer)
this.setState({renderSeq: seqToRender})
}
// empty the input field
this.setState({userInput: ''})
}
}
chatOptionHandler = (res) => {
let choice = ''
switch (res) {
case 'give me a shout.':
choice = "a";
// also need to add this to the chatContent?
break;
case 'what?':
choice = "b";
break;
case 'but why?':
choice = "c";
break;
case 'tell me.':
choice = "d";
break;
default:
choice = null;
}
return choice
}
// input: option from the user
// output: random line from the data object
updateChatContent = (opt) => {
try {
let selectedLine;
if (optionCount[opt] <= FakeData.response[opt].length - 1){
selectedLine = FakeData.response[opt][optionCount[opt]]
optionCount[opt] += 1
} else {
optionCount[opt] = 0
selectedLine = FakeData.response[opt][optionCount[opt]]
}
return selectedLine;
}
catch(error) {
console.error(error);
return 'line blackhole'
}
}
resHandler = (res) => {
let currSeq = this.state.currSeq
let nextSeq = this.state[currSeq][res]
// valid next sequence was found
if (nextSeq){
this.setState({
prevSeq: currSeq,
currSeq: nextSeq,
renderSeq: nextSeq
})
return nextSeq
} else { // invalid, there is no nextseq according to the input
// if the currea is 'invalid', render backontrackseq
if (currSeq === 'Invalid'){
return 'Invalid'
} else { // if the currseq is not 'invalid', render Invalid
this.setState({
backontrackseq: currSeq,
Invalid: {
start: 'Landing',
back: currSeq,
},
prevSeq: currSeq,
currSeq: 'Invalid',
renderSeq: 'Invalid'
})
return 'Invalid'
}
}
}
handleFile = (file) => {
const reader = new FileReader();
reader.onload = (event) => {
const file = event.target.result;
const allLines = file.split(/\r\n|\n/);
// Reading line by line
allLines.forEach((line) => {
// IMLEMENT
// from text, get patterns and write it in a json format
console.log(line);
});
};
reader.onerror = (event) => {
alert(event.target.error.name);
};
reader.readAsText(file);
}
handleFile = (file) => {
const reader = new FileReader();
reader.onload = (event) => {
const file = event.target.result;
const allLines = file.split(/\r\n|\n/);
// Reading line by line
allLines.forEach((line) => {
console.log(line);
});
};
reader.onerror = (event) => {
alert(event.target.error.name);
};
reader.readAsText(file);
}
render() {
console.log("[APP] this.state.currSeq:",this.state.currSeq)
let optionToRender = this.state.optionToRender
console.log("[APP] optionToRender", optionToRender)
let chatContentAll = this.state.chatContent
// render line by line
let chatLineComp = chatContentAll.map((line, i) => {
return <ChatLine key={i} lineContent = {line}/>
})
return (
<div className="App">
<Layout>
{this.state.currSeq === 'Upload'?
<Terminal sequence={this.state.renderSeq}>
<div className="upload">
<input
type="file"
id="file"
className="input-file"
accept=".txt"
onChange={(e) => this.handleFile(e.target.files[0])}
/>
</div>
<Prompt userInput = {this.state.userInput}/>
<input
type="text"
onChange={this.inputChangedHandler}
onKeyPress={this.keyPressedHandler}
value={this.state.userInput} />
</Terminal>
:
<Terminal sequence={this.state.renderSeq}>
<Prompt userInput = {this.state.userInput}/>
<input
type="text"
onChange={this.inputChangedHandler}
onKeyPress={this.keyPressedHandler}
value={this.state.userInput} />
</Terminal>
}
<Chat
choice={this.state.userAnswer}
optionToRender={this.state.optionToRender}
content={this.state.chatContent}>
{chatLineComp}
</Chat>
</Layout>
</div>
);
}
}
export default App;