Should I build a local data layer/app state to maintain state in a React Native/Firestore App?

不想你离开。 提交于 2020-05-24 02:23:27

问题


A main selling point of Firestore is the ability to use it as a online/offline source of truth. I'm using it in this way right now: updating the Firestore document directly on an action, then listening to Firestore DB changes and mapping this back to local state. However, relying on this latency compensation and mapping back to local state is not sufficient for quick updates (taps, toggles even with a small document size). For example, toggles will "jitter" as the RN toggle presumptively shifts on tap, and the local state hasn't been updated until it already returns see video example. It appears worse on Android and the problem isn't strictly limited to basic toggles.

  1. Does document size or query result size have a bigger impact on latency compensation? Our document size is very small right now with a worst case ~1000 query result set. We could make the documents 1000x bigger (100kb) and have a query result set of size 1. Update: Testing appears inconsistent here, latency compensation is not ideal in either case
  2. Which of the following other things may impact latency compensation?

    • Using queries with custom indexes. Note: we're not currently reading from cache, we're using the JS SDK
    • Multiple writes. Would multiple writes to the same document make it worse (4 quick writes vs. 2 quick writes). Update: not clear this makes a big difference.
    • Using the native vs. JS module. We're currently using the Firestore Web SDK with an Expo app. Update: switching to native module via React-Native Firestore has no apparent performance improvement.
  3. Is it common for people to build a local data shim layer / local app state with React Native / Firestore apps to help improve local performance speed? Are there any suggested libraries for this?

On app load, mount the listener, and export the result to context to be used through the app

const [user, setUser] = useState();

firebase.firestore().collection(`users/${user.uid}`).onSnapshot(qs => setUser(oldState => {
    const newState = {};
    qs.docChanges().forEach(change => {
      if (change.type === "added" || change.type === "modified") {
        newState[change.doc.id] = {
          docid: change.doc.id,
          ...change.doc.data(),
        };
      } else if (change.type === "removed") {
        delete oldState[change.doc.id];
      }
    });

    return {
      ...oldState,
      ...newState,
    };
  }))

Sample component and function to toggle notifications: (switch is jittery)

const toggleNotifications = (user, value) => {
  firebase.firestore().doc(`users/${user.uid}`).update({
    wantNotifications: value,
  });
};

const TestComponent = () => {
  //gets from context, set in listener mounted on app load
  const { user } = useUserContext();
  return (
    <Switch
      value={user.wantNotifications}
      onValueChange={value => toggleNotifications(user, value)}
    />
  );
};

回答1:


This not an answer, just a long comment :)

@learningAngular For example, in toggleNotifications just need to call an async action creator and don't worry about putting any logic inside react component.

Instead Redux pattern gives space to do some logics, in this case because user's last moment decision is source of truth so dispatch function would always set a local tempState and updatingStatus before start updating firestore, then after firestore promise either resolved or rejected dispatches an action to reducer to reset updatingStatus. Then a selector would check if updatingStatus is true to just rely on local tempState otherwise rely on listened firestore state. Finally, react component use selector result as currently valid state.

I am not answering this question because I don't have that much experience. I am also curious if a good solution is out there, but this is what I think is the solution at this moment.




回答2:


I updated the answer with specific learnings, but after a lot of testing, my biggest general learnings so far are

  • Latency compensation can be very inconsistent even with the same data and environment. Listeners can take time to "warm up", as is mentioned in other questions. It is hard to have a standard metric here.
  • Document size DOES impact latency compensation. Everything else so far is inconclusive.


来源:https://stackoverflow.com/questions/61254151/should-i-build-a-local-data-layer-app-state-to-maintain-state-in-a-react-native

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!