这是一个React组件,允许上传文本文件。文件内容稍后将显示在组件中。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getFile } from '../actions/fileActions';
import toJsonArray from '../utils/toJsonArray';
class TableInput extends Component {
constructor() {
super();
this.state = {
file: {},
jsonArr: []
};
this.onFileUpload = this.onFileUpload.bind(this);
}
componentWillReceiveProps(nextProps) {
const { file } = nextProps.file;
if (file) {
this.setState({ file });
}
if (file) {
let readFromFile;
const reader = new FileReader();
reader.onload = event => {
readFromFile = event.target.result;
this.setState({ jsonArr: toJsonArray(readFromFile) }, () => console.log('jsonArr:', this.state.jsonArr));
};
reader.onerror = error => console.log(error);
reader.readAsText(file);
}
}
componentDidUpdate(_, prevState) {
if (this.state.jsonArr.length) {
console.log('this.state.jsonArr:', this.state.jsonArr);
}
}
onFileUpload() {
const file = document.querySelector('input[type=file]').files[0];
this.props.getFile(file);
}
render() {
return (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
<th>Description</th>
<th>Date</th>
<th>Billable</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>TableInput</td>
<td>{this.state.file.name}</td>
<td>{this.state.jsonArr['Memo'] ? 'it exists' : 'it does not'}</td>
</tr>
</tbody>
</table>
<label htmlFor='files' className='file-input-label'>
Select File
</label>
<input type='file' id='files' className='file-input-hidden' onChange={this.onFileUpload} />
</div>
);
}
}
const mapStateToProps = state => ({
file: state.file
});
export default connect(mapStateToProps, { getFile })(TableInput);
这里实际上不需要州的file
属性。通过file
操作将上载的this.props.getFile(file)
发送到适当的reducer。
在jsonArr
的{{1}}调用内,this.setState({ jsonArr: toJsonArray(readFromFile) })
属性已正确填充了json对象数组。
如何在状态上新设置的componentWillReceiveProps(nextProps)
属性显示在jsonArr
内部?
到目前为止,我的render()
空着。我想我可以使用<td>
,但还没有弄清楚该怎么做。
componentDidUpdate()
操作:
getFile()
相应的减速器
import { FILE_UPLOAD } from './types';
// dispatch uploaded file
export const getFile = (file) => (dispatch) => {
dispatch({
type: FILE_UPLOAD,
payload: file
});
};
用于返回json数组的import { FILE_UPLOAD } from '../actions/types';
const initialState = {
file: {}
};
export default function(state = initialState, action) {
switch(action.type) {
case FILE_UPLOAD:
return {
...state,
file: action.payload
};
default:
return state;
}
};
util方法。该数组由具有toJsonArray()
对的json对象组成。
key: value
答案 0 :(得分:0)
解决方案是对this.setState()
中上载的文本文件中的每个键应用componentWillReceiveProps(nextProps)
。该代码需要清除以外的其他内容。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getFile } from '../actions/fileActions';
import toJsonArray from '../utils/toJsonArray';
class TableInput extends Component {
constructor() {
super();
this.state = {
file: {}, // as stated in the origin question not needed
jsonArr: [], // not needed either
'Incurred Date': [],
'Memo': [],
'Person Name': [],
'Amount': [],
'Billable': [],
'Entry Date': [],
'Comment': [],
length: 0,
fileName: ''
};
this.onFileUpload = this.onFileUpload.bind(this);
}
componentWillReceiveProps(nextProps) {
const { file } = nextProps.file;
if (file) {
this.setState({ file });
}
if (file) {
let readFromFile;
const reader = new FileReader();
reader.onload = event => {
readFromFile = event.target.result;
const jsonArray = toJsonArray(readFromFile);
// various keys inside quotes below come from the uploaded file
this.setState({
'Incurred Date': jsonArray.map(item => item['Incurred Date']),
'Memo': jsonArray.map(item => item['Memo']),
'Person Name': jsonArray.map(item => item['Person Name']),
'Amount': jsonArray.map(item => item['Amount']),
'Billable': jsonArray.map(item => item['Billable']),
'Entry Date': jsonArray.map(item => item['Entry Date']),
'Comment': jsonArray.map(item => item['Comment']),
length: jsonArray.length,
fileName: file.name
});
};
reader.onerror = error => console.log(error);
reader.readAsText(file);
}
}
onFileUpload() {
const file = document.querySelector('input[type=file]').files[0];
this.props.getFile(file);
}
render() {
let rows = [];
if (this.state.length) {
for (let i = 0; i < this.state.length; i++) {
rows.push(
<tr key={i}>
<td>{this.state['Person Name'] && this.state['Person Name'][i]}</td>
<td>{this.state['Amount'] && this.state['Amount'][i]}</td>
{this.state['Memo'] && this.state['Memo'][i] && <td>{this.state['Memo'][i]}</td>}
{this.state['Comment'] && this.state['Comment'][i] && <td>{this.state['Comment'][i]}</td>}
{this.state['Incurred Date'] && this.state['Incurred Date'][i] && <td>{this.state['Incurred Date'][i]}</td>}
{this.state['Entry Date'] && this.state['Entry Date'][i] && <td>{this.state['Entry Date'][i]}</td>}
<td>{this.state['Billable'] && this.state['Billable'][i]}</td>
<td>{this.state.fileName === 'expenses.csv' ? 'Expense' : 'Time'}</td>
</tr>
)
}
}
return (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
<th>Description</th>
<th>Date</th>
<th>Billable</th>
<th>Type</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
<label htmlFor='files' className='file-input-label'>Select File</label>
<input type='file' id='files' className='file-input-hidden' onChange={this.onFileUpload} />
</div>
);
}
}
const mapStateToProps = state => ({
file: state.file
});
export default connect(mapStateToProps, { getFile })(TableInput);