Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to refresh remote data programmatically #383

Closed
billBeOK opened this issue Mar 27, 2019 · 17 comments
Closed

How to refresh remote data programmatically #383

billBeOK opened this issue Mar 27, 2019 · 17 comments

Comments

@billBeOK
Copy link

Help me pls,

I have bind data to MaterialTable with remote feature without problems.
But now i want to be able to refresh this data with a trigger. I don't know if it is possible?

I know how to do it when data is an array. (with state)
but when data is a promise ....

Thks,

async fetchUsers(query){
 let datas = await fetch("/datas")
 return {  data: datas, page: query.page, totalCount: datas.length}
}
refreshAllMyRemoteData(){
  // here i want to be able to refresh the data but i don't know how to do it :)
}
...

<MaterialTable
  data={this.fetchUsers}
  detailPanel={[
    {
      icon: 'person_add_disabled',
      render: rowData => {
        return (<div onClick={this.refreshAllMyRemoteData}>click-me</div>)
      },
    }
  ]}
@mbrn mbrn closed this as completed in dc033cb Mar 27, 2019
mbrn added a commit that referenced this issue Mar 27, 2019
@mbrn
Copy link
Owner

mbrn commented Mar 27, 2019

Hi @billBeOK ,

Your requirement makes sense. I resolved it with tableRef with new version 1.28.0

import { Grid, MuiThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import MaterialTable from './material-table';

class App extends Component {
  tableRef = React.createRef();

  render() {
    return (
        <div style={{ maxWidth: '100%', direction }}>        
              <MaterialTable
                tableRef={this.tableRef}
                columns={[
                  {
                    title: 'Avatar',
                    field: 'avatar',
                    render: rowData => (
                      <img
                        style={{ height: 36, borderRadius: '50%' }}
                        src={rowData.avatar}
                      />
                    ),
                  },
                  { title: 'Id', field: 'id' },
                  { title: 'First Name', field: 'first_name' },
                  { title: 'Last Name', field: 'last_name' },
                ]}
                data={query =>
                  new Promise((resolve, reject) => {
                    let url = 'https://reqres.in/api/users?';
                    url += 'per_page=' + query.pageSize;
                    url += '&page=' + (query.page + 1);
                    fetch(url)
                      .then(response => response.json())
                      .then(result => {
                        resolve({
                          data: result.data,
                          page: result.page - 1,
                          totalCount: result.total,
                        })
                      });
                  })
                }
                title="Remote Data Example"
              />
          <button
            onClick={() => {
              this.tableRef.current.onQueryChange();
            }}
          >
            ok
          </button>
        </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);

module.hot.accept();

@billBeOK
Copy link
Author

it's work like a charm !

Bravo

@ahmedbrandver
Copy link

Help me please I am getting this this.tableRef.current.onQueryChange() undefined

@twhetzel
Copy link

I also had the error initially and then realized I missed tableRef = React.createRef(); right after class App extends Component {

@fershibli
Copy link

Is there a way to change query before refreshing data?

@twhetzel
Copy link

twhetzel commented Oct 4, 2019

In addition to having the search trigger on pressing the Enter key, I also added a "Clear" button with

clearSearchInput = () => {
        // clear value
        this.setState({
            value: '',
        })
        // refresh table
        this.tableRef.current.onQueryChange();
    }

@fxbayuanggara
Copy link

fxbayuanggara commented Mar 14, 2020

this.tableRef.current.onQueryChange();

the ref and this.tableRef.current.onQueryChange() saved my life bro! It works with functional component too using useRef!

@kalandarisvili
Copy link

this.tableRef.current.onQueryChange();

the ref and this.tableRef.current.onQueryChange() saved my life bro! It works with functional component too using useRef!

Could you please share a functional component example?

@saqfish
Copy link

saqfish commented Mar 27, 2020

this.tableRef.current.onQueryChange();

the ref and this.tableRef.current.onQueryChange() saved my life bro! It works with functional component too using useRef!

Could you please share a functional component example?

using mbrn's previous code but with hooks:

import { Grid, MuiThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import MaterialTable from './material-table';
const App = () => {
  tableRef = useRef();
    return (
        <div style={{ maxWidth: '100%', direction }}>        
              <MaterialTable
                tableRef={tableRef}
                columns={[
                  {
                    title: 'Avatar',
                    field: 'avatar',
                    render: rowData => (
                      <img
                        style={{ height: 36, borderRadius: '50%' }}
                        src={rowData.avatar}
                      />
                    ),
                  },
                  { title: 'Id', field: 'id' },
                  { title: 'First Name', field: 'first_name' },
                  { title: 'Last Name', field: 'last_name' },
                ]}
                data={query =>
                  new Promise((resolve, reject) => {
                    let url = 'https://reqres.in/api/users?';
                    url += 'per_page=' + query.pageSize;
                    url += '&page=' + (query.page + 1);
                    fetch(url)
                      .then(response => response.json())
                      .then(result => {
                        resolve({
                          data: result.data,
                          page: result.page - 1,
                          totalCount: result.total,
                        })
                      });
                  })
                }
                title="Remote Data Example"
              />
          <button
            onClick={() => tableRef.current.onQueryChange()}
          >
            ok
          </button>
        </div>
    );
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
); 

A quick edit, but I think you get the point.

@swanandev
Copy link

this.tableRef.current.onQueryChange();

the ref and this.tableRef.current.onQueryChange() saved my life bro! It works with functional component too using useRef!

Could you please share a functional component example?

using mbrn's previous code but with hooks:

import { Grid, MuiThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import MaterialTable from './material-table';
const App = () => {
  tableRef = useRef();
    return (
        <div style={{ maxWidth: '100%', direction }}>        
              <MaterialTable
                tableRef={tableRef}
                columns={[
                  {
                    title: 'Avatar',
                    field: 'avatar',
                    render: rowData => (
                      <img
                        style={{ height: 36, borderRadius: '50%' }}
                        src={rowData.avatar}
                      />
                    ),
                  },
                  { title: 'Id', field: 'id' },
                  { title: 'First Name', field: 'first_name' },
                  { title: 'Last Name', field: 'last_name' },
                ]}
                data={query =>
                  new Promise((resolve, reject) => {
                    let url = 'https://reqres.in/api/users?';
                    url += 'per_page=' + query.pageSize;
                    url += '&page=' + (query.page + 1);
                    fetch(url)
                      .then(response => response.json())
                      .then(result => {
                        resolve({
                          data: result.data,
                          page: result.page - 1,
                          totalCount: result.total,
                        })
                      });
                  })
                }
                title="Remote Data Example"
              />
          <button
            onClick={() => tableRef.current.onQueryChange()}
          >
            ok
          </button>
        </div>
    );
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
); 

A quick edit, but I think you get the point.

When, I use the tableRef.current.OnQueryChange(), it throws an error saying _this.props.data is not a function.

Can Someone Help on it

Here's a screenshot

Damn Error!

@saqfish
Copy link

saqfish commented Apr 9, 2020

this.tableRef.current.onQueryChange();

the ref and this.tableRef.current.onQueryChange() saved my life bro! It works with functional component too using useRef!

Could you please share a functional component example?

using mbrn's previous code but with hooks:

import { Grid, MuiThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import MaterialTable from './material-table';
const App = () => {
  tableRef = useRef();
    return (
        <div style={{ maxWidth: '100%', direction }}>        
              <MaterialTable
                tableRef={tableRef}
                columns={[
                  {
                    title: 'Avatar',
                    field: 'avatar',
                    render: rowData => (
                      <img
                        style={{ height: 36, borderRadius: '50%' }}
                        src={rowData.avatar}
                      />
                    ),
                  },
                  { title: 'Id', field: 'id' },
                  { title: 'First Name', field: 'first_name' },
                  { title: 'Last Name', field: 'last_name' },
                ]}
                data={query =>
                  new Promise((resolve, reject) => {
                    let url = 'https://reqres.in/api/users?';
                    url += 'per_page=' + query.pageSize;
                    url += '&page=' + (query.page + 1);
                    fetch(url)
                      .then(response => response.json())
                      .then(result => {
                        resolve({
                          data: result.data,
                          page: result.page - 1,
                          totalCount: result.total,
                        })
                      });
                  })
                }
                title="Remote Data Example"
              />
          <button
            onClick={() => tableRef.current.onQueryChange()}
          >
            ok
          </button>
        </div>
    );
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
); 

A quick edit, but I think you get the point.

When, I use the tableRef.current.OnQueryChange(), it throws an error saying _this.props.data is not a function.

Can Someone Help on it

Here's a screenshot

Damn Error!

Post your code?

@swanandev
Copy link

swanandev commented Apr 9, 2020

Sry, I forgot in hurry

const colHeads = columns.map((cl)=>{
return cl==='kills'||cl==='rank'||cl==='wallet'
? {title:colValues[cl],field:cl,type:'numeric',editable: 'onUpdate'}
: {title:colValues[cl],field:cl,editable: 'never'}
});

const colData = players && players.map((pl,ind)=>{
    let cp={}
    columns && columns.map((cl,cind)=>{
        return cl==='srno'? cp[cl]=players.indexOf(pl)+1 : cp[cl]=pl[cl]
    })
    return cp;
})


const tRef = React.useRef();

const editF = {
    onRowAdd:null,
    onRowUpdate:(newData,oldData)=>
    new Promise((resolve,reject)=>{
        setTimeout(()=>{
        let data = colData;
        console.log(state)
        let inx = data.indexOf(oldData);
        newData['kills']=parseInt(newData['kills'])
        newData['wallet']=parseInt(newData['wallet'])
        newData['rank']=parseInt(newData['rank'])
        data[inx] = newData;
        resolve();
        },1000)
    }),
    onRowDelete : null
};

const tRF = ()=>{
    setState(state)
}
return(
    <React.Fragment>
        <div>
            <MaterialTable
                tableRef={tRef}
                title="Players"
                columns={colHeads}
                data={colData}
                editable={isEditing? editF : null}
            />
            <button
        onClick={() => {
          tRef.current.onQueryChange();
        }}
      >
        ok
      </button>
            <div hidden={!bttnname}>
                <button onClick={()=>tRF()}  className='waves-effect waves-light btn hoverable'>{bttnname}</button>
            </div>
        </div>
    </React.Fragment>
)

The data is displayed properly, But when I try to use state for data and use setState(), it causes another error so, I opted for this approach.

@saqfish
Copy link

saqfish commented Apr 9, 2020

Sry, I forgot in hurry

const colHeads = columns.map((cl)=>{
return cl==='kills'||cl==='rank'||cl==='wallet'
? {title:colValues[cl],field:cl,type:'numeric',editable: 'onUpdate'}
: {title:colValues[cl],field:cl,editable: 'never'}
});

const colData = players && players.map((pl,ind)=>{
    let cp={}
    columns && columns.map((cl,cind)=>{
        return cl==='srno'? cp[cl]=players.indexOf(pl)+1 : cp[cl]=pl[cl]
    })
    return cp;
})


const tRef = React.useRef();

const editF = {
    onRowAdd:null,
    onRowUpdate:(newData,oldData)=>
    new Promise((resolve,reject)=>{
        setTimeout(()=>{
        let data = colData;
        console.log(state)
        let inx = data.indexOf(oldData);
        newData['kills']=parseInt(newData['kills'])
        newData['wallet']=parseInt(newData['wallet'])
        newData['rank']=parseInt(newData['rank'])
        data[inx] = newData;
        resolve();
        },1000)
    }),
    onRowDelete : null
};

const tRF = ()=>{
    setState(state)
}
return(
    <React.Fragment>
        <div>
            <MaterialTable
                tableRef={tRef}
                title="Players"
                columns={colHeads}
                data={colData}
                editable={isEditing? editF : null}
            />
            <button
        onClick={() => {
          tRef.current.onQueryChange();
        }}
      >
        ok
      </button>
            <div hidden={!bttnname}>
                <button onClick={()=>tRF()}  className='waves-effect waves-light btn hoverable'>{bttnname}</button>
            </div>
        </div>
    </React.Fragment>
)

The data is displayed properly, But when I try to use state for data and use setState(), it causes another error so, I opted for this approach.

It's hard to follow what your doing, but it seems like you don't need to use data in this manner in the first place. If you aren't dealing directly with remote data like in the previous example, you should fix your state problem. Good luck!

@swanandev
Copy link

Sry, I forgot in hurry
const colHeads = columns.map((cl)=>{
return cl==='kills'||cl==='rank'||cl==='wallet'
? {title:colValues[cl],field:cl,type:'numeric',editable: 'onUpdate'}
: {title:colValues[cl],field:cl,editable: 'never'}
});

const colData = players && players.map((pl,ind)=>{
    let cp={}
    columns && columns.map((cl,cind)=>{
        return cl==='srno'? cp[cl]=players.indexOf(pl)+1 : cp[cl]=pl[cl]
    })
    return cp;
})


const tRef = React.useRef();

const editF = {
    onRowAdd:null,
    onRowUpdate:(newData,oldData)=>
    new Promise((resolve,reject)=>{
        setTimeout(()=>{
        let data = colData;
        console.log(state)
        let inx = data.indexOf(oldData);
        newData['kills']=parseInt(newData['kills'])
        newData['wallet']=parseInt(newData['wallet'])
        newData['rank']=parseInt(newData['rank'])
        data[inx] = newData;
        resolve();
        },1000)
    }),
    onRowDelete : null
};

const tRF = ()=>{
    setState(state)
}
return(
    <React.Fragment>
        <div>
            <MaterialTable
                tableRef={tRef}
                title="Players"
                columns={colHeads}
                data={colData}
                editable={isEditing? editF : null}
            />
            <button
        onClick={() => {
          tRef.current.onQueryChange();
        }}
      >
        ok
      </button>
            <div hidden={!bttnname}>
                <button onClick={()=>tRF()}  className='waves-effect waves-light btn hoverable'>{bttnname}</button>
            </div>
        </div>
    </React.Fragment>
)

The data is displayed properly, But when I try to use state for data and use setState(), it causes another error so, I opted for this approach.

It's hard to follow what your doing, but it seems like you don't need to use data in this manner in the first place. If you aren't dealing directly with remote data like in the previous example, you should fix your state problem. Good luck!

Really Thanks, for the quick reply. I'll go with it then!

@vopecula
Copy link

Just a sidenote. If you want to trigger the data reload on the table from one of your action button handlers which holds some async functions, and you have a problem like your reference is null, than the following might help you:

// Example is for a functional component

const yourRef = React.createRef()

// ...

tableRef: {yourRef},
actions: {[
  rowData => ({
    // ...
    onClick: (event, rowData) => {
      const scopedRef = yourRef.current
      anAsyncFunction(/*...*/).then(() => scopedRef.onQueryChange())
    }
  })
]}

// ...

@AravindTReddy
Copy link

For any one who is looking for doing the same with their custom API you can check this
https://stackoverflow.com/questions/67816193/handling-the-table-pagination-when-refreshing-remote-data-programmatically

@AbdulhakimZ
Copy link

I'm trying to add data from one table to another on doubleclick. everything is working fine but when I try to refresh the other table using tableRef.current.OnQueryChange() as you've done above it shows this error.

image

_this.props.data is not a function. ...

I'm tired of dealing with this problem. I this is a bug or I missed something.

This is the code in material-table.js line 342:
_this.props.data(query).then(function (result) {......

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests