最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Table Component is not re-rendered after state update - Stack Overflow

programmeradmin5浏览0评论

i'm having a table ponent for displaying some data. After dispatching an action the table data in the state are channging. However my table ponent is not updated. It is updated only when i click on another radio button in another row of my table. I want my ponent to rerender when the data are changed. Here is my code:

const mapStateToProps = state => ({
  evaluationData: evaluationResultsSelector(state)
});

const mapDispatchToProps = dispatch => ({
  setSelectedEvaluationRecord: record =>
    dispatch(setSelectedEvaluationRecord(record))
});


export default connect(mapStateToProps,
  mapDispatchToProps
  EvaluationDataTable,  
);

and my ponent is this:

import React from 'react';
import Table from 'antd/lib/table';
import 'antd/lib/table/style/css';
import "antd/dist/antd.css";
import { columnEvaluation } from './evaluationDataStructure';

class EvaluationDataTable extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedRowKeys: [0], // Check here to configure the default column
    };
  }
  // shouldComponentUpdate(prevProps, prevState) {
  //   return (prevProps.results !== this.props.results || prevState.selectedRowKeys !== this.state.selectedRowKeys);
  // }
  onRowChange = selectedRowKeys => {
    if (selectedRowKeys.length > 1) {
      const lastSelectedRowIndex = [...selectedRowKeys].pop();
      this.setState({ selectedRowKeys: lastSelectedRowIndex });
    }
    this.setState({ selectedRowKeys });
  };

  onRowSelect = (record) => {
    this.props.setSelectedEvaluationRecord(record)
  };

  render() {
    const { selectedRowKeys } = this.state;
    const rowSelection = {
      type: 'radio',
      selectedRowKeys,
      onChange: this.onRowChange,
      onSelect: this.onRowSelect
    };
    return (
      <React.Fragment>
        <div style={{ marginBottom: 16 }} />
        <Table
          rowSelection={rowSelection}
          columns={columnEvaluation}
          dataSource={this.props.evaluationData}
        />
      </React.Fragment>
    );
  }
}

export default EvaluationDataTable;

When i click in another row the table is rerendered as my setState is triggered but when the data are channged the table is not rerendered. Only when i click in another row. How to deal with it? Thanks a lot

Also my reducer which mutates the table is this:

case ACTION_TYPES.EDIT_EVALUATION_RESULTS: {
      const evaluationResults = state.evaluationResults;
      const editedRecord = action.payload.editedEvaluationData;
      evaluationResults.forEach((item, i)  => {
        if (item.id === editedRecord.id) {
          evaluationResults[i] = editedRecord;
        }
      });
      return {
        ...state,
        evaluationResults
      };
    }

i'm having a table ponent for displaying some data. After dispatching an action the table data in the state are channging. However my table ponent is not updated. It is updated only when i click on another radio button in another row of my table. I want my ponent to rerender when the data are changed. Here is my code:

const mapStateToProps = state => ({
  evaluationData: evaluationResultsSelector(state)
});

const mapDispatchToProps = dispatch => ({
  setSelectedEvaluationRecord: record =>
    dispatch(setSelectedEvaluationRecord(record))
});


export default connect(mapStateToProps,
  mapDispatchToProps
  EvaluationDataTable,  
);

and my ponent is this:

import React from 'react';
import Table from 'antd/lib/table';
import 'antd/lib/table/style/css';
import "antd/dist/antd.css";
import { columnEvaluation } from './evaluationDataStructure';

class EvaluationDataTable extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedRowKeys: [0], // Check here to configure the default column
    };
  }
  // shouldComponentUpdate(prevProps, prevState) {
  //   return (prevProps.results !== this.props.results || prevState.selectedRowKeys !== this.state.selectedRowKeys);
  // }
  onRowChange = selectedRowKeys => {
    if (selectedRowKeys.length > 1) {
      const lastSelectedRowIndex = [...selectedRowKeys].pop();
      this.setState({ selectedRowKeys: lastSelectedRowIndex });
    }
    this.setState({ selectedRowKeys });
  };

  onRowSelect = (record) => {
    this.props.setSelectedEvaluationRecord(record)
  };

  render() {
    const { selectedRowKeys } = this.state;
    const rowSelection = {
      type: 'radio',
      selectedRowKeys,
      onChange: this.onRowChange,
      onSelect: this.onRowSelect
    };
    return (
      <React.Fragment>
        <div style={{ marginBottom: 16 }} />
        <Table
          rowSelection={rowSelection}
          columns={columnEvaluation}
          dataSource={this.props.evaluationData}
        />
      </React.Fragment>
    );
  }
}

export default EvaluationDataTable;

When i click in another row the table is rerendered as my setState is triggered but when the data are channged the table is not rerendered. Only when i click in another row. How to deal with it? Thanks a lot

Also my reducer which mutates the table is this:

case ACTION_TYPES.EDIT_EVALUATION_RESULTS: {
      const evaluationResults = state.evaluationResults;
      const editedRecord = action.payload.editedEvaluationData;
      evaluationResults.forEach((item, i)  => {
        if (item.id === editedRecord.id) {
          evaluationResults[i] = editedRecord;
        }
      });
      return {
        ...state,
        evaluationResults
      };
    }
Share Improve this question edited May 26, 2019 at 0:20 RamAlx asked May 25, 2019 at 18:41 RamAlxRamAlx 7,34424 gold badges64 silver badges110 bronze badges 7
  • 1 Problem likely has something to do with your reducer setup. Can you post your code for it? – Cat_Enthusiast Commented May 25, 2019 at 19:07
  • 1 @ChristopherNgo you were so right..i change this evaluationResults to this evaluationResults : [...evaluationResults] – RamAlx Commented May 26, 2019 at 0:42
  • 1 haha yeah I saw that... you were doing a state-mutation. I was just going to tell you to spread it in a new array instead. I'm glad you took the time to figure it out and learned a little more about redux-principles. – Cat_Enthusiast Commented May 26, 2019 at 0:43
  • 1 Thanks a lot!! If you want add this as an answer so as to gain more points. ;) – RamAlx Commented May 26, 2019 at 0:45
  • 1 That is very much appreciated :) – Cat_Enthusiast Commented May 26, 2019 at 0:46
 |  Show 2 more ments

1 Answer 1

Reset to default 15

Problem was here as OP has already deduced.

 const evaluationResults = state.evaluationResults;

This was causing a state-mutation which goes against Redux principles. Although the state values were being updated in OP's proceeding code, the changes were being made to the same, initial object in reference. Redux does not register it as a new-state so it found no need to re-render our ponent. To get your connected-ponent to re-render we need a pletely new redux-state.

To achieve this, we need to create a brand-new copy of evaluationResults like so and then the OP's feature will work as expected:

const evaluationResults = [...state.evaluationResults];
发布评论

评论列表(0)

  1. 暂无评论