useState hook value is stale inside of onSnapshot #1920
-
Hello - I have an const Store = types.model('Store', {
arr: types.array(types.array(types.array(types.number)))
}).actions((self) => {
const setArr = (next) => {
self.arr = next;
}
}); const doSomeCompute = (nextArr) => returnSomeValuesBasedOnArr(nextArr);
// I am using useContext to pass the store stuff around
const ObservedComponent = observer(({arr}) => {
const [state, setState] = useState(doSomeCompute(arr);
onSnapshot(arr, (snap) => {
const next = doSomeCompute(snap);
// this fails because `state` is always the initial value
if (equals(next, state) {
return;
}
setState(next);
});
return (
<SomeBasicComponentThatNeedsTheStateValue {...state} />;
);
}); |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Hi @kwhitaker! The easiest solution might be to make the computed value into a const Store = types
.model("Store", {
arr: types.array(types.array(types.array(types.number)))
})
.views((self) => ({
get computation() {
return doSomeCompute(self.arr);
}
}))
.actions((self) => ({
setArr(next) {
self.arr = next;
}
}));
// ...
const ObservedComponent = observer(({ computation }) => {
return <SomeBasicComponentThatNeedsTheStateValue {...computation} />;
}); If you absolutely don't want to pollute your MST model with this computation you could use the const ObservedComponent = observer(({ arr }) => {
const state = useLocalObservable(() => ({
arr, // The initial arr value
get computation() {
return doSomeCompute(state.arr);
}
}));
useEffect(() => {
// Sync the arr from 'props' into the observable 'state'
state.arr = arr;
}, [arr]);
return <SomeBasicComponentThatNeedsTheStateValue {...state.computation} />;
}); |
Beta Was this translation helpful? Give feedback.
Hi @kwhitaker!
The easiest solution might be to make the computed value into a
view
and it will be kept in sync automatically:If you absolutely don't want to pollute your MST model with this computation you could use the
useLocalObservable
hook and derive the computed ("v…