joy08
joy08

Reputation: 9652

Not able to setstate with respect to array of objects: React JS

I am trying to map few fields in array of objects, here in this case it is fieldnames and sort order.

I am trying to achieve server side sorting functionality where in the server takes the field name and sort type whenever I click on a field. I just need to map the field names with the sort type(ASCENDING or DESCENDING) .

I have written a sample where I am maintaining a sample array of objects with type. And on click of that column need I need to decide its sorting order

Can someone help here , Just need to achieve the tagging of sort order with the field name

Sandbox: https://codesandbox.io/s/hopeful-wescoff-08x8x

import React from "react";
import ReactDOM from "react-dom";
import { render } from "react-dom";

interface IState {
  sorting: any;
}
interface IProps {}

export default class App extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      sorting: [{ firstName: "" }, { lastName: "" }]
    };
  }

  sortHandler = name => {
    const sorting = Object.keys(this.state.sorting).reduce((obj, key) => {
      if (key === name) {
        obj[key] = this.state.sorting[key] === "ASC" ? "DESC" : "ASC";
      } else {
        obj[key] = "";
      }
      return obj;
    }, {});

    this.setState({ sorting }, () => console.log(this.state.sorting));
  };

  render() {
    return (
      <div>
        <span onclick={this.sortHandler("firstName")}> FirstName</span>
        <span onclick={this.sortHandler("lastName")}> LastName</span>
      </div>
    );
  }
}

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



Upvotes: 1

Views: 189

Answers (2)

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

Your click-handlers get executed immediately on render and with the logic you have constructed this will cause the "Maximum update depth exceeded" error.

Pass an anonymous function that will call your sortHandler instead. This will make it so the sortHandler only gets executed when the user clicks the span:

  render() {
    return (
      <div>
        <span onclick={() => this.sortHandler("firstName")}> FirstName</span>
        <span onclick={() => this.sortHandler("lastName")}> LastName</span>
      </div>
    );
  }

See sandbox for example on how to sort by fieldnames: https://codesandbox.io/s/vigilant-haslett-c2z3f

Upvotes: 5

import React from "react";
import ReactDOM from "react-dom";
//import { render } from "react-dom";

interface IState {
  sorting: any;
}
interface IProps {}

export default class App extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      sorting: [{ firstName: "" }, { lastName: "" }]
    };
  }

  sortHandler = (name => {
    const sorting = Object.keys(this.state.sorting).reduce((obj, key) => {
      if (key === name) {
        obj[key] = this.state.sorting[key] === "ASC" ? "DESC" : "ASC";
      } else {
        obj[key] = "";
      }
      return obj;
    }, {});

    this.setState({ sorting }, () => console.log(this.state.sorting));
  });

  render() {
    return (
      <div>
        <span onclick={() => this.sortHandler("firstName")}> FirstName</span>
        <span onclick={() => this.sortHandler("lastName")}> LastName</span>
      </div>
    );
  }
}

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

Few Highlighted issue on your code, please do not import the code if you're not using which can consume memory.

Arrow function dedicated to using the function on the scope. Please check the scope of the variable if the variable required bind with scope

    const sorting = Object.keys(this.state.sorting).reduce((obj, key) => {

Please make sure the calling function also requires the scope this to the function. I hope your problem is solved by the initial solution. its just additional notes

Upvotes: 0

Related Questions