7

I'm using the material-table component, which I fill with dynamic data coming from Redux (an array of objects), but then I do other things with that data inside my component's state. To create column dropdown filters, there's an element inside each column's array of options, lookup, that receives an object and creates the dropdown based on it's values. I am extracting some items from my data and putting them inside an element in my component's state. This is an object, the same kind that lookup receives. The thing is that the component shows an empty dropdown, as if the object was empty, but it's not. I'm logging it in into the console and the object is filled with the data I need. I initially thought it was a render problem, that the object is empty at the beggining, and then it's filled with data, but the component renders every time.(Yeah, React is reactive). This is only the code needed to help me solve this problem:

Table component

import React, { Component } from "react";
import MaterialTable from "material-table";

class CustomTable extends Component {
  state = {
    column1: "",
    column2: "",
    column3: "",
    column1FilterList: {}
    columns: [
      {
        title: "Column1",
        field: "column1",
        editable: "onAdd",
        filtering: true,
        lookup: { ...this.column1FilterList }
      },
      {
        title: "Column2",
        field: "column2",
        editable: "onAdd",
        filtering: true,
      },
      {
        title: "Column3",
        field: "column3",
        editable: "onAdd",
        filtering: true
      }
    ]
  };

  componentDidMount() {
    this.props.fetchValues()
    this.props.fetchApplications()
    this.filterColumn1ExistingKeys()
  }

  filterColumn1ExistingKeys = () => {
    return this.props.elements.map(element => {
       return this.setState(prevState => ({
           column1FilterList: {
              ...prevState.column1FilterList,
             [element.name]: element.name
           }
       }))
    })
  }

  render() {
    return (
      <div>
        <MaterialTable
          options={{
            search: false,
            actionsColumnIndex: 4,
            filtering: true
          }}
          title="Search by"
          columns={this.state.columns}
          data={this.state.data}
        />
      </div>
    );
  }
}

export default CustomTable;
Shubham Verma
  • 4,918
  • 1
  • 9
  • 22
TheWoodStudio
  • 213
  • 5
  • 13
  • Where do you use **filterColumn1ExistingKeys** function?? – Shubham Verma Aug 02 '19 at 19:13
  • In `componentDidMount()`. I forgot to paste it. Now the code is edited. – TheWoodStudio Aug 02 '19 at 19:18
  • Can you put your code in codesandbox. I Still didn't get it. What is CustomTable there is two-component you using. How other function work in componentDidMount?? – Shubham Verma Aug 02 '19 at 19:21
  • I don't think I can do that. It's work related. Sorry about the copy errors. There's a lot of code. Fixed the component. – TheWoodStudio Aug 02 '19 at 19:24
  • Its hard to tell from this code. try making small POC and see what's happening on code sandbox. – Shubham Verma Aug 02 '19 at 19:26
  • The problem is the object that appears empty when giving it to `lookup`. No console errors, nothing. I also think I'm setting the new state right in the `filterColumn1ExistingKeys` function. I will try to make a CodeSandbox. – TheWoodStudio Aug 02 '19 at 19:28

1 Answers1

3

The problem is how you save that data. You create a new object in the constructor with { ...this.column1FilterList }. This will create a new object which will act as the lookup object, which is filled with the initial data of column1FilterList (empty). Updating the column1FilterList later does not change that lookup object, because it is disconnected (new object). You have to update the lookup within the columns as well like this:

const filterColumn1ExistingKeys = () => {
  const column1FilterList = this.state.column1FilterList;
  this.props.elements.forEach(element => column1FilterList[element.name] = element.name)
  this.setState({
    column1FilterList,
    columns: [{
      title: "Column1",
      field: "column1",
      editable: "onAdd",
      filtering: true,
      lookup: { ...column1FilterList }
    },
    {
      title: "Column2",
      field: "column2",
      editable: "onAdd",
      filtering: true,
    },
    {
      title: "Column3",
      field: "column3",
      editable: "onAdd",
      filtering: true
    }
    ]
  })
}

Hope this helps. Let me know, if that works for you. If you have any questions, let me know. Happy coding.

Domino987
  • 8,475
  • 2
  • 15
  • 38
  • Hey! Thank you for your response. I really don't get your solution. Why do I need to update the `lookup` with the columns? Also, the refactor you do to the filter... function has a few syntax errors. Is that right? I'm sorry. Hope you can clarify a bit. Thank you anyway for taking time doing this. – TheWoodStudio Aug 05 '19 at 13:08
  • @TheWoodStudio Lets discuss it in a chat: https://chat.stackoverflow.com/rooms/197497/dynamic-lookup-from-reacts-state-in-material-table – Domino987 Aug 05 '19 at 13:20