Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table Component is not re-rendered after state update

i'm having a table component for displaying some data. After dispatching an action the table data in the state are channging. However my table component is not updated. It is updated only when i click on another radio button in another row of my table. I want my component 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 component 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
      };
    }
like image 634
user7334203 Avatar asked May 25 '19 18:05

user7334203


People also ask

Does updating state re-renders component?

There are four reasons why a component would re-render itself: state changes, parent (or children) re-renders, context changes, and hooks changes. There is also a big myth: that re-renders happen when the component's props change. By itself, it's not true (see the explanation below).

How do I make my component Rerender on state change?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically. However, there may be cases where the render() method depends on some other data.

Will a React component reset its state when it re-renders?

You're rendering a different component in the same position, so React resets all state below.

How do you stop a component from rendering even after state has been updated?

To prevent the render method from being called, set the return to false, which cancels the render. This method gets called before the component gets rendered. Sometimes you may want to prevent re-render even if a component's state or prop has changed.


1 Answers

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 component. To get your connected-component to re-render we need a completely 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];
like image 166
Chris Ngo Avatar answered Oct 17 '22 01:10

Chris Ngo