From 8af5aafb4ac68b0d7f79f68700b6b87ba07a1ce8 Mon Sep 17 00:00:00 2001 From: Yauheni Pasiukevich Date: Mon, 24 Jul 2023 15:00:17 +0200 Subject: [PATCH] fix: state management flow to avoid data loss Signed-off-by: Yauheni Pasiukevich --- lib/withOnyx.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/withOnyx.js b/lib/withOnyx.js index 7dc8e5a42..ca1742a1e 100644 --- a/lib/withOnyx.js +++ b/lib/withOnyx.js @@ -121,14 +121,15 @@ export default function (mapOnyxToState) { return; } - const stateUpdate = {...this.tempState, loading: false}; + // Leave untouched previous state to avoid data loss during pre-load updates. + // This handles case when setState was called before the setWithOnyxState. + // For example, when an Onyx property was updated by keyChanged before the call of the setWithOnyxState. + this.setState((prevState) => { + const remainingTempState = _.omit(this.tempState, _.keys(prevState)); - // The state is set here manually, instead of using setState because setState is an async operation, meaning it might execute on the next tick, - // or at a later point in the microtask queue. That can lead to a race condition where - // setWithOnyxState is called before the state is actually set. This results in unreliable behavior when checking the loading state and has been mainly observed on fabric. - this.state = stateUpdate; + return ({...remainingTempState, loading: false}); + }); - this.setState(stateUpdate); // Trigger a render delete this.tempState; }