Reputation: 1275
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
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
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
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}</>;
};
Upvotes: 1