You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 Memo property: use jsonArr.some(item => item.Memo)
  • Render all parsed items: use map to 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 jsonArr in the component's state—this will simplify the code even more.
  • The some method checks if any item in the array has a Memo property, which fixes your original display issue.
  • Using map to render rows ensures all your parsed file content is displayed in the table.

内容的提问来源于stack exchange,提问作者El Anonimo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:27:40