0

I don't know exactly what is my problem. I used some library. When i use callback and trying to get state of Component, the state always is default value.

Example when i use mui-datatables https://github.com/gregnb/mui-datatables

import React, { useState } from 'react'
import MUIDataTable from "mui-datatables";

const columns = [
    {
        name: "name",
        label: "Name",
    },
    {
        name: "company",
        label: "Company",
    },
    {
        name: "city",
        label: "City",
    },
    {
        name: "state",
        label: "State",
    },
];

const data = [
    { name: "Joe James", company: "Test Corp", city: "Yonkers", state: "NY" },
    { name: "John Walsh", company: "Test Corp", city: "Hartford", state: "CT" },
    { name: "Bob Herm", company: "Test Corp", city: "Tampa", state: "FL" },
    { name: "James Houston", company: "Test Corp", city: "Dallas", state: "TX" },
];


const MyComponent = () => {

    const [myState, setMyState] = useState("default value");
    const onRowClick = (rowData, rowMeta) => {
        console.log(myState) //always default value
    }

    const options = {
        onRowClick: onRowClick 
    }
    return (
        <div>
            <MUIDataTable
                title={"Employee List"}
                data={data}
                columns={columns}
                options={options}
            />

            <button onClick={ () => setMyState("State changed")}>Change state</button>
            <p>{myState}</p>

        </div>
    )
}

First, I click button to change MyState, the state changed in p tag. Next, I click any row to console MyState. But, it's always is default value. Why? Code in CodeSanBox: https://codesandbox.io/s/dreamy-germain-tuylh

mikenlanggio
  • 1,122
  • 1
  • 7
  • 27
  • I'm getting this error with your code on CodeSandbox: `Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?` Have you tried with a class component? – cbdeveloper May 28 '19 at 07:54
  • I updated Codesanbox. Hope you can help! – mikenlanggio May 28 '19 at 08:09

3 Answers3

0

I have converted your component to a class, and now it's working as you wanted. You can see below the error that was happening when you were trying to use a functional component. This is probably due to how mui-datatables is built. It probably requires a class component to work.

Working example on CodeSandbox

import React from "react";
import ReactDOM from "react-dom";

import MUIDataTable from "mui-datatables";

const columns = [
  {
    name: "name",
    label: "Name"
  },
  {
    name: "company",
    label: "Company"
  },
  {
    name: "city",
    label: "City"
  },
  {
    name: "state",
    label: "State"
  }
];

const data = [
  { name: "Joe James", company: "Test Corp", city: "Yonkers", state: "NY" },
  { name: "John Walsh", company: "Test Corp", city: "Hartford", state: "CT" },
  { name: "Bob Herm", company: "Test Corp", city: "Tampa", state: "FL" },
  { name: "James Houston", company: "Test Corp", city: "Dallas", state: "TX" }
];

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      myState: "default value"
    };
    this.options = { onRowClick: this.onRowClick };
    this.onRowClick = this.onRowClick.bind(this);
  }

  onRowClick(rowData, rowMeta) {
    console.log(this.state.myState); //always default value
  }

  render() {
    return (
      <div>
        <MUIDataTable
          title={"Employee List"}
          data={data}
          columns={columns}
          options={{ onRowClick: this.onRowClick }}
        />

        <button onClick={() => this.setState({ myState: "State changed" })}>
          Change state
        </button>
        <p>{this.state.myState}</p>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<MyComponent />, rootElement);

With your code, I was get the following error:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `WithStyles(Tooltip)`.
    in Tooltip (created by WithStyles(Tooltip))
    in WithStyles(Tooltip) (created by t)
    in t (created by l)
    in span (created by l)
    in div (created by l)
    in div (created by ForwardRef(Toolbar))
    in ForwardRef(Toolbar) (created by WithStyles(ForwardRef(Toolbar)))
    in WithStyles(ForwardRef(Toolbar)) (created by l)
    in l (created by t)
    in t (created by WithStyles(t))
    in WithStyles(t) (created by t)
    in t (created by t)
    in div (created by ForwardRef(Paper))
    in ForwardRef(Paper) (created by WithStyles(ForwardRef(Paper)))
    in WithStyles(ForwardRef(Paper)) (created by t)
    in t (created by WithStyles(t))
    in WithStyles(t) (created by MyComponent)
    in div (created by MyComponent)
    in MyComponent
cbdeveloper
  • 27,898
  • 37
  • 155
  • 336
  • No. You can use `@material-ui/core` ver 3.9.3. And get no error – mikenlanggio May 28 '19 at 08:12
  • In my CodeSanbox, it's being used `@material-ui/core v4.0.1`. What I mean is that is just nothing wrong with your code, that should be 100% working. Because you're seeing the updated state in the `

    ` tag. It means that react re-rendered and updated the state. And in that re-render, react recreated your `onRowClick` function. There's no way you should be logging the previous state. Unless something is not right with the component you're using, which is `MUIDataTable`. And you can see the error that React was throwing when you tried with a functional component.

    – cbdeveloper May 28 '19 at 08:17
  • But i used some other library. And i get same problem. I don't want to use `Class Component` just because the problem i don't know why it happened. I don't think the library have problems.. – mikenlanggio May 28 '19 at 08:19
  • But have you got success doing this with a functional component at any point? For me, it looks that it's not possible. Check out this issue from `mui-datatables` [Link](https://github.com/gregnb/mui-datatables/issues/649). > Hooks are not yet officially supported by mui-datatables, so you use these new features at your own risk. You have to mind the peer dependency versions of this project. – cbdeveloper May 28 '19 at 08:24
  • And before hooks came along, `state` was only possible using classes. Maybe that's why you can't do it with hooks. Even if it works in `3.9.3`, I encourage you to use the later version and do it with classes. Or find another library that uses React Hooks built-in. – cbdeveloper May 28 '19 at 08:27
  • There are some people trying to get around this error on this [issue on mui-datatables](https://github.com/gregnb/mui-datatables/issues/595). – cbdeveloper May 28 '19 at 08:28
  • But the fact is that you don't have a bug in your code. Right now you have a bug in your library of choice because it's not compatible with React Hooks. – cbdeveloper May 28 '19 at 08:30
0

It's something with mui-table. Looks like it does not handle if options.rowClickis changed. I've put breakpoint into MUIDataTable.render() and it's called just once. Providing different options does not re-render that.

So if I add key like

<MUIDataTable
  key={myState}
  ...

to force it be re-created instead of updating - it works and State changed is displayed in console.

But maybe it'd be better to file issue in their github. Or try most recent version.

skyboyer
  • 22,209
  • 7
  • 57
  • 64
0

I was able to solve a similar problem by utilizing the useRef hook. Reference this answer for more information.

Bernard
  • 1,004
  • 1
  • 12
  • 21