José Carlos
José Carlos

Reputation: 2922

How to reload data in a table in React

I have developed a component which receive data from another component (father). The component who receives the data, the first time, show the data correctly, but the second time, don't do it.

The second time the metho componentWillReceiveProps is called and I have implemented this. But, despite that, the data is not refreshed.

To see the data of this second call, I need to send data to component child a third time and in this moment I will see the data of the second call.

The code of the component child is:

import React, {Component} from "react";
import { Button, Spinner } from "react-bootstrap";
import BootstrapTable from 'react-bootstrap-table-next';
import { columnsTTShootingFEB, sortedTTShootingFEB } from "../../FEBCOM/column.tables";
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
import "../../../css/content.css";

/**
 * This constat let me have a row with buttons who show or hide columns 
 * 
 * @param {*} param0 
 */
const CustomToggleList = ({
    columns,
    onColumnToggle,
    toggles
  }) => (
    <div className="btn-group btn-group-toggle" data-toggle="buttons" style = {{width: 100 + "%"}}>
      {
        columns
          .map(column => ({
            ...column,
            toggle: toggles[column.dataField]
          }))
          .map((column, index) => {
              if (index > 1){
                return (<button
                type="button"
                key={ column.dataField }
                className={ `btn btn-success btn-sm ${column.toggle ? 'active' : ''}` }
                data-toggle="button"
                aria-pressed={ column.toggle ? 'true' : 'false' }
                onClick={ () => onColumnToggle(column.dataField) }
                >
                    { column.text }
                </button>)
              }
            })
      }
    </div>
  );

class TTShooting extends Component{
    constructor(props){
        super(props);
        this.props = props;
        this.state = {
            loaded: false
        };
    }
componentDidMount(){
    console.log("Componente cargado");
    console.log("id_team_club 1: " + this.props.teams_std_stats[0].id_team_club);
    this.setState({
        loaded: true,
        teams_std_stats: this.props.teams_std_stats
    });
}

componentWillReceiveProps(nextProps){
    this.props = nextProps;
    console.log("id_team_club 2: " + this.props.teams_std_stats[0].id_team_club);
    this.setState({
        teams_std_stats: this.props.teams_std_stats
    });
    console.log("Componente recibe nuevos datos");
}

render(){
    return(
        <div>
            {
                (this.state.loaded) ?
                    <div>
                        {
                            (this.props.language === "es") ?
                                <div>
                                <ToolkitProvider
                                    keyField="id_team_club"
                                    data={ this.state.teams_std_stats }
                                    columns={ columnsTTShootingFEB }
                                    columnToggle
                                    >
                                    {
                                        props => (
                                        <div>
                                            <p className = "text-justify" style = {{fontSize: 12 + "pt"}}><b>Nota: </b>Para añadir o eliminar columnas en la tabla basta hacer clic sobre uno de estos botones</p>
                                            <CustomToggleList { ...props.columnToggleProps } />                                                
                                            <hr />
                                            <BootstrapTable
                                            { ...props.baseProps }
                                            footerClasses = "footer-class"
                                            defaultSorted = { sortedTTShootingFEB }
                                            />
                                        </div>
                                        )
                                    }
                                </ToolkitProvider>
                                </div>
                            :
                                <h2>Pendiente de desarrollo</h2>                                
                        }
                    </div>
                :
                    <div style = {{marginTop: 10 + "px"}}>
                        <Button variant="dark" disabled>
                            <Spinner
                                as="span"
                                animation="border"
                                size="sm"
                                role="status"
                                aria-hidden="true"
                            />
                            <span className="sr-only">
                                {(this.props.language === "es") ? "Cargando datos ..." : "Loading data ..."}
                            </span>
                        </Button>{' '}
                        <Button variant="dark" disabled>
                            <Spinner
                                as="span"
                                animation="grow"
                                size="sm"
                                role="status"
                                aria-hidden="true"
                                />
                                {(this.props.language === "es") ? "Cargando datos ..." : "Loading data ..."}
                        </Button>                    
                    </div>                    
            }
        </div>
    )
}
}

module.exports.TTShooting = TTShooting; 

This code returns a log when is called the first time and other times. The first time returns:

> id_team_club 1: 769

This is correct. When I send new data is called the method componentWillReceiveProps, I update the props and the state and show the id_team_club of the firs element and this is the same. The method is called twice.

> id_team_club 2: 769 
> Componente recibe nuevos datos
> id_team_club 2
> Componente recibe nuevos datos

But, if I send data again, then I show the data of the second send of data in the second call to the function:

> id_team_club 2: 769
> Componente recibe nuevos datos
> **id_team_club 2: 720**
> Componente recibe nuevos datos

What am I doing wrong? How can I update the data of the table?

Edit

I have updated the code of componentWillReceiveProps and how I pass the data to the table.

componentWillReceiveProps(nextProps){
    if (this.props.teams_std_stats !== nextProps.teams_std_stats) {
        console.log("Vamos a modificar el state");
        this.setState({
          teams_std_stats: nextProps.teams_std_stats
        });
      }
}

                            <ToolkitProvider
                                keyField="id_team_club"
                                data={ this.state.teams_std_stats }
                                columns={ columnsTTShootingFEB }
                                columnToggle
                                >
                                {
                                    props => (
                                    <div>
                                        <p className = "text-justify" style = {{fontSize: 12 + "pt"}}><b>Nota: </b>Para añadir o eliminar columnas en la tabla basta hacer clic sobre uno de estos botones</p>
                                        <CustomToggleList { ...props.columnToggleProps } />                                                
                                        <hr />
                                        <BootstrapTable
                                        { ...props.baseProps }
                                        footerClasses = "footer-class"
                                        defaultSorted = { sortedTTShootingFEB }
                                        />
                                    </div>
                                    )
                                }
                            </ToolkitProvider>

But, it doesn't work.

Upvotes: 1

Views: 3661

Answers (4)

halfer
halfer

Reputation: 20440

(Posted a solution on behalf of the question author to move the answer to the answer space).

The problem was due to the data. Because didn't arrive correctly. These data are get it by a query to database after an event and when I assign the id of the element which fire the event this was not assigning correctly to the state.

To assign correctly the value to the state I have to do this:

async handleChange(event){
    /**
     * If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove
     * the synthetic event from the pool and allow references to the event to be retained by user code.
     */
    event.persist();
let season = this.state.seasons.find((item) => {
    return parseInt(item.id) === parseInt(event.target.value)
});        

this.setState({
    itemSelected: season.id,
});
}

Upvotes: 1

Jagrati
Jagrati

Reputation: 12222

Do not mutate the props in lifecycle methods. The render function will always have the updated props, you do not need to set this.props.

  componentWillReceiveProps(nextProps) {
    if (this.props.teams_std_stats !== nextProps.teams_std_stats) {
      this.setState({
        teams_std_stats: nextProps.teams_std_stats
      });
    }
  }

Also setting this.props = props inside constructor is wrong.

constructor(props){
        super(props);
        this.state = {
            loaded: false
        };
    }

Upvotes: 1

Gerardo Sabetta
Gerardo Sabetta

Reputation: 559

As others have pointed the problem is related to modifying the props, but I also wanted to add that I see no need to take team_std_stats and to make it part of your component state, you can reference that straight from the props in your render function, why not just do that?

try this line

data={ this.props.teams_std_stats }

instead of

 data={ this.state.teams_std_stats }

for your <ToolkitProvider /> implementation.

Hope that helps.

Upvotes: 0

S. Hesam
S. Hesam

Reputation: 6603

You should not change the props in react, the props of a component are read-only. This expression is incorrect:

 this.props = nextProps;

Please read this article about props props-are-read-only

Upvotes: 3

Related Questions