React组件中如何在render中渲染更新后的jsonArr状态?
Let's break down your issues and fix them step by step:
1. 核心问题:错误的数组访问逻辑
Your jsonArr is an array of JSON objects, but in the render method you're trying to access it like an object with this.state.jsonArr['Memo']. Arrays use index-based access, so this will always return undefined—that's why you're seeing "it does not" no matter what.
2. 次要问题:废弃的生命周期与冗余数据流
componentWillReceiveProps has been deprecated since React 16.3, and storing raw File objects in Redux is not ideal (they're reference types that can cause unexpected behavior). Your current data flow (upload → dispatch file to Redux → read file in component via props) is unnecessarily convoluted.
Fix Steps
Step 1: Correct Array Access in Render
To check for the presence of Memo or render your parsed data, work with the array properly:
- Check if any item has a
Memoproperty: usejsonArr.some(item => item.Memo) - Render all parsed items: use
mapto loop through the array and generate table rows
Step 2: Simplify File Handling Logic
You don't need to store the raw File in Redux. Instead, read and parse the file directly in the component, then dispatch the parsed array to Redux only if you need it elsewhere in your app. This eliminates the need for the deprecated lifecycle method.
Step 3: Replace Deprecated Lifecycle (If Using Redux)
If you still want to use Redux for the parsed data, use componentDidUpdate to listen for props changes instead of componentWillReceiveProps.
Updated Full Component Code
import React, { Component } from 'react'; import { connect } from 'react-redux'; import { getParsedJsonArr } from '../actions/fileActions'; // Updated action for parsed data import toJsonArray from '../utils/toJsonArray'; class TableInput extends Component { constructor() { super(); this.state = { jsonArr: [] }; this.onFileUpload = this.onFileUpload.bind(this); } // Listen for Redux props updates (if needed) componentDidUpdate(prevProps) { if (this.props.parsedJsonArr !== prevProps.parsedJsonArr) { this.setState({ jsonArr: this.props.parsedJsonArr }); } } onFileUpload(e) { const file = e.target.files[0]; if (!file) return; // Read and parse file directly in the component const reader = new FileReader(); reader.onload = (event) => { const fileContent = event.target.result; const jsonArr = toJsonArray(fileContent); this.setState({ jsonArr }, () => { // Dispatch parsed array to Redux only if needed elsewhere this.props.getParsedJsonArr(jsonArr); }); }; reader.onerror = (error) => console.error('File read error:', error); reader.readAsText(file); } render() { const { jsonArr } = this.state; const selectedFile = document.querySelector('input[type=file]').files?.[0]; 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> {/* Display basic file info */} <tr> <td>TableInput</td> <td>{selectedFile?.name || 'No file selected'}</td> <td>{jsonArr.some(item => item.Memo) ? 'Memo exists in file' : 'Memo does not exist'}</td> </tr> {/* Render all parsed data rows */} {jsonArr.map((item, index) => ( <tr key={index}> <td>{item.Name || '-'}</td> <td>{item.Amount || '-'}</td> <td>{item.Memo || '-'}</td> <td>{item.Date || '-'}</td> <td>{item.Billable || '-'}</td> <td>{item.Type || '-'}</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 => ({ parsedJsonArr: state.file.parsedJsonArr }); export default connect(mapStateToProps, { getParsedJsonArr })(TableInput);
Corresponding Redux Updates (If Using Redux)
Updated Action:
import { FILE_UPLOAD_PARSED } from './types'; // Dispatch parsed JSON array instead of raw file export const getParsedJsonArr = (jsonArr) => (dispatch) => { dispatch({ type: FILE_UPLOAD_PARSED, payload: jsonArr }); };
Updated Reducer:
import { FILE_UPLOAD_PARSED } from '../actions/types'; const initialState = { parsedJsonArr: [] }; export default function(state = initialState, action) { switch(action.type) { case FILE_UPLOAD_PARSED: return { ...state, parsedJsonArr: action.payload }; default: return state; } };
Key Notes
- If you don't need the parsed data elsewhere in your app, you can remove all Redux-related code entirely and just manage
jsonArrin the component's state—this will simplify the code even more. - The
somemethod checks if any item in the array has aMemoproperty, which fixes your original display issue. - Using
mapto render rows ensures all your parsed file content is displayed in the table.
内容的提问来源于stack exchange,提问作者El Anonimo

