Loading data into grid on click returns Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘dataState’)

I have a grid created using a React library that I want to fill with data with an API call once the user clicks on a button called Fetch Products. Currently, my grid does not get populated and I get this error when I debug it:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'dataState')

and I am not sure why. Why isn’t the grid populating properly and what else can I do? Here is my code:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Grid, GridColumn as Column } from '@progress/kendo-react-grid';
import { process } from '@progress/kendo-data-query';
import {
  setExpandedState,
  setGroupIds,
} from '@progress/kendo-react-data-tools';
const initialDataState = {
  take: 10,
  skip: 0,
  products: [],
  group: [
    {
      field: 'id',
    },
  ],
};

const processWithGroups = (data, dataState) => {
  const newDataState = process(data, dataState);
  setGroupIds({
    data: newDataState.data,
    group: dataState.group,
  });
  return newDataState;
};

const fetchAllData = () => {
  fetch(
    'https://otp.metroservices.io/otp/routers/default/index/routes/uscalacmtarail:801/stops'
  )
    .then((response) => response.json())
    .then((productsList) => {
      const newDataState = processWithGroups(
        productsList,
        this.state.dataState
      );
      this.setState({
        products: productsList, // update the data
        result: newDataState, // update the procesed data
      });
    });
};

const FirstButton = () => {
  return (
    <div>
      <button type="button" onClick={fetchAllData}>
        Fetch Products
      </button>
    </div>
  );
};

class App extends React.PureComponent {
  state = {
    dataState: initialDataState,
    result: processWithGroups(initialDataState.products, initialDataState),
    collapsedState: [],
    products: [],
  };


  dataStateChange = (event) => {
    const newDataState = processWithGroups(
      this.state.products, // use the none processed data
      event.dataState
    );
    this.setState({
      result: newDataState,
      dataState: event.dataState,
    });
  };

  expandChange = (event) => {
    const item = event.dataItem;

    if (item.groupId) {
      const newCollapsedIds = !event.value
        ? [...this.state.collapsedState, item.groupId]
        : this.state.collapsedState.filter(
            (groupId) => groupId !== item.groupId
          );
      this.setState({
        collapsedState: newCollapsedIds,
      });
    }
  };

  // componentDidMount() {
  //   this.fetchAllData()
  // }

  render() {
    const newData = setExpandedState({
      data: this.state.result.data, // pass the proccessed data
      collapsedIds: this.state.collapsedState,
    });
    return (
      <div>
        <FirstButton />
        <Grid
          style={{
            height: '520px',
          }}
          resizable={true}
          reorderable={true}
          filterable={true}
          sortable={true}
          groupable={true}
          data={newData}
          onDataStateChange={this.dataStateChange}
          {...this.state.dataState}
          onExpandChange={this.expandChange}
          expandField="expanded"
        >
          <Column field="id" filterable={false} title="ID" width="50px" />
          <Column field="name" title="Name" />
          <Column field="cluster" title="Cluster" filter="numeric" />
        </Grid>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.querySelector('my-app'));

Answer

this.state.dataState does not exist in fetchAllData.

You need to pass the this.state.dataState in App to FirstButton then to fetchAllData. After all that, you can use that