Andrew Dormi
Andrew Dormi

Reputation: 119

Why react does not trigger component update?

I have custom list with custom methods. Trying to change list and call setState does not trigger component update

import React, {useState} from "react";

class MyCustomArray extends Array {
    push(item) {
        super.push(item);
        return this;
    }
}

export default () => {
    const [items, setItems] = useState(new MyCustomArray());
    console.log(items)
    return (
        <div>
            {items.length}
            <button onClick={() => setItems(items.push(1))}/>
        </div>
    );
}

I have tried same method using class component instead of function and it works.

import React, {Component} from "react";

class MyCustomArray extends Array {
    push(item) {
        super.push(item);
        return this;
    }
}

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {items: new MyCustomArray()};
    }

    render() {
        const {items} = this.state;
        return (
            <div>
                {items.length}
                <button onClick={() => this.setState({items: items.push(1)})}/>
            </div>
        );
    }
}

Upvotes: 1

Views: 78

Answers (1)

Taki
Taki

Reputation: 17654

You need a new instance of items array, use the spread syntax,

import React, { useState } from "react";

class MyCustomArray extends Array {
  push(item) {
    super.push(item);
    return this;
  }
}

export default () => {
  const [items, setItems] = useState(new MyCustomArray());

  return (
    <div>
      {items.length}
      <button onClick={() => setItems([...items, 1])} />
      //                              ^^^^^^^^^^^^^
    </div>
  );
};

Same thing if you want to use a class Component :

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = { items: new MyCustomArray() };
  }

  updateItems = (item) => {
    this.setState(prevState => ({
      ...prevState,
      items: [...prevState.items, item]
    }));
  }

  render() {
    const { items } = this.state;
    return (
      <div>
        {items.length}
        <button onClick={() => this.updateItems(1)} />
      </div>
    );
  }
}

Upvotes: 1

Related Questions