JungHsuan / react-native-collapsible-tabview

This is only an implementation of tabview with collapsible header.
MIT License
284 stars 60 forks source link

Lazy load #16

Open tcorreiaubi opened 3 years ago

tcorreiaubi commented 3 years ago

Thank you for the amazing job implementing and sharing this code with us as a base for multiple use cases. Have you tried to implement lazy loading? I have been trying to implement it and facing some issues related to the scrollOffSet of the lazy loaded tabs, I'm facing the issue that you explain on the medium post where you introduce the syncScrollOffset to cover all the tabs scroll and keep them in sync, this won't work for lazy loading because the listRefArr does not hold the references for the tabs that are not yet loaded. I'm trying to come up with a solution, but since you worked with the base idea maybe you know some "workaround" for this situation? Meantime if I find a way of handling it I will post here for further reference in case someone needs it.

boxcc commented 3 years ago

I tried the following code and it seems to work

<Animated.FlatList
    ...
    contentOffset={{ x: 0, y: (scrollY as any)._value }}    // <--------- this
    onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], {
        useNativeDriver: true,
    })}
    ...
/>
tcorreiaubi commented 3 years ago

I ended up changing to https://github.com/PedroBern/react-native-collapsible-tab-view

JungHsuan commented 3 years ago

Sorry for my late reply. This is how I achieve lazy load: First, enable lazy load in react-native-tab-view

<TabView 
lazy={true} 
...
 />

The tricky part is that if we simply enable lazy, you would find the scroll offset of unloaded tab is not well synced. It is because that the scene is not loaded yet, so we couldn't update the offset by syncSelfScrollOffset. As a result, we just need to update the offset while scene is loaded.

onGetRef: ref => {
    if (ref) {
        const found = sceneListRef.current.find(e => e.key === route.key);
        if (!found) {
              sceneListRef.current.push({
                key: route.key,
                value: ref,
         });
         syncSelfScrollOffset(route.key);  // update here
       }
    }
},

Here we also need to modify syncSelfScrollOffset slightly to accept a route key to make it work.

  const syncSelfScrollOffset = routekey => {
    if (props.routes?.length <= 0 || !props.scenes) {
      return;
    }
    // here we need to get ref by key
    const currentLoadedRouteRef = sceneListRef.current.find(
      r => r.key === routekey
    );
    if (currentLoadedRouteRef != null) {
      const item = currentLoadedRouteRef;
      ....
      ....
  };