heapOverflow
heapOverflow

Reputation: 1275

How to make a react component update when a self-updating prop changes?

I have an object that self-updates. Let's say every second it changes its state.

export class Obj {

  val = 0;

  start = () => {
    setInterval(() => {
     this.update();
    }, 1000);
  }

  update = () => {
    this.val++;
  }

}

I think (please correct me if I'm wrong) that a similar alternative would be an object connected to a stream of data, changing its state every few ms to the last value received.

I now want a react component (using hooks) that displays this:

function C(obj) {

  return <div>{obj.val}</div>

}

My question is, how can I make the component C change when the val of obj changes? I could use a callback on every change, but it feels like I'd be polluting my models only for the sake of React. An alternative would be to move the interval outside of Obj into the React component but that might not be what I want, and would not cover the case of a stream.

Is there a standard approach in React to update a (functiona, hook based) component when some of its props changes its state?

Upvotes: 2

Views: 3429

Answers (3)

Max Lysenko
Max Lysenko

Reputation: 341

In this case component C won't be re-rendered since its props (obj) has never been changed. Objects are compared by reference and since it is the same object reference that was before nothing happens.

You can use component C like this to make it re-render: <C value={obj.val} />, so on every obj.val update it will react correspondingly since its prop now is changing.

Also you could have this logic inside:

const obj = new Obj();

function C() {
  const [value, setValue] = React.useState(0);
  
  React.useEffect(() => {
    const interval = setInterval(() => {
      setValue(value + 1);
    }, 1000);

    return () => {
      clearInterval(interval); // don't forget to do cleanup
    }; 
  }, []);

  return <div>{value}</div>
}

Upvotes: 0

garritfra
garritfra

Reputation: 578

The component needs to have a state, which can be updated via the setState method. When you have a changing prop, it might make sense to provide a callback method from your react component, which, when called, executes setState under the hood.

Upvotes: 0

Dennis Vash
Dennis Vash

Reputation: 53874

To update React component you need to use any React API, render component's parent (if not memoized), or change its props. Updating the value of an object/class won't notify React.

There are many approaches to make React aware of the object change like the one you described.

A less familiar one is using this.forceUpdate it manually forces a render of a component, it widely uses in React wrappers for common libraries.

Here is a usage example with hooks:

class Obj {
  val = 0;

  start = sideEffect => {
    setInterval(() => {
      this.update();
      sideEffect();
    }, 1000);
  };

  update = () => {
    this.val++;
    console.log(this.val);
  };
}

const obj = new Obj();

const App = () => {
  const [, render] = useReducer(p => !p, false);
  useEffect(() => {
    const renderOnUpdate = () => {
      obj.start(render);
    };
    renderOnUpdate();
  }, []);

  return <>{obj.val}</>;
};

Edit distracted-mountain-r2hyt

Upvotes: 1

Related Questions