Home > Blockchain >  Custom Classes and "Observing" changes with useEffect in React/Typescript
Custom Classes and "Observing" changes with useEffect in React/Typescript

Time:01-13

I have simplified my issue in a code-sandbox for ease of a demo. Think of this counter class as a more complex external Lib.

Explanation

I have a Class that has a property of a count and method that will increment that count.

interface Counter {
  count: number;
  increment(): void;
  autoIncrement(): void;
}

export class MyCounter implements Counter {
  public count: number;

  constructor() {
    this.count = 0;
  }

  public increment() {
    this.count = this.count   1;
    console.log(this.count);
  }
  autoIncrement() {
    setInterval(() => {
      this.count = this.count   1;
    }, 1000);
  }
}

In a react app I initialise the class and put it in a Memo to prevent unnecessary initialisations of it.

  const counter = useMemo(() => {
    return new MyCounter();
  }, []);

Then I display the count in my React App along with a button to increment it.

I then "observe" the changes of the button click in a useEffect like this:

  useEffect(() => {
    console.log("counter", counter.count);
  }, [counter]);

but clicking the button and incrementing the count does not update in the React component.

Why is that? In my understanding of Hooks it should work but I might be fundamentally miss understanding what is happening here.

I have tried passing the class instance to a Child component and using it as props, still to no avail.

CodePudding user response:

...but clicking the button and incrementing the count does not update in the React component.

Why is that?

Because the value in counter, which is a reference to the Counter object, didn't change; modifying the count property doesn't create a new object. If you want to observe changes to counter.count, that's what should be in the dependency array:

useEffect(() => {
    console.log("counter", counter.count);
}, [counter.count]);
//         ^^^^^^

(Or you might use [counter, counter.count].)

But, if you're using counter.count when rendering, it should be in state so changes to it cause re-rendering. (And if counter is in state, you need to create a new instance each time you increment the counter, because you can't directly modify state objects.)

CodePudding user response:

React js component re-render only if state changed or props changed here in your case. the counter.count is not a props and not a state so your App.js will not re-render to display the new value of count variable. I didn't get why you use new class to do that you can simply do it with state.

  •  Tags:  
  • Related