Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect pages when content changes dynamically [iOS] #597

Closed
yuri-lomashko-itechart opened this issue Sep 2, 2022 · 6 comments
Closed
Assignees
Labels
hacktoberfest hacktoberfest

Comments

@yuri-lomashko-itechart
Copy link

yuri-lomashko-itechart commented Sep 2, 2022

Environment

Platform: iOS
react-native: 0.69.5
react-native-pager-view: 5.4.25

Description

I use the library for vertical scroll of fullscreen pages and receive few pages from BE. In cases when number of pages is changed I see the empty screens or not the whole list of pages. It's hard to say when it happens exactly, but in example bellow it can be reproduced in 80% cases. Also if to add some additional render then issue can be reproduced more frequent

Reproducible Demo

Video

Screen.Recording.2022-09-02.at.16.35.50.mov

Code sample

import { useState } from 'react';
import { Button, SafeAreaView, Text, View } from 'react-native';
import PagerView from 'react-native-pager-view';

const ids = ['first', 'second', 'third'];

function getNewArray() {
  return ids.reduce<string[]>((array, id) => {
    if (Math.round(Math.random())) {
      array.push(id);
    }
    return array;
  }, []);
}

export const Test = () => {
  const [, setCounter] = useState(0);
  const [pagesContent, setPagesContent] = useState<string[]>([]);

  console.log(pagesContent);

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <Text style={{ textAlign: 'center' }}>{pagesContent.length}</Text>
      <PagerView orientation={'vertical'} overdrag={false} style={{ flex: 1 }}>
        {pagesContent.map((content) => (
          <View key={content}>
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
              <Text style={{ fontSize: 30 }}>{content}</Text>
            </View>
          </View>
        ))}
      </PagerView>
      <Button
        title={'Set with random'}
        onPress={() => {
          setPagesContent(getNewArray());
          // to get more frequent effect, one of the next lines can be used
          // setCounter((prev) => prev + 1);
          // setImmediate(() => setCounter((prev) => prev + 1));
        }}
      />
    </SafeAreaView>
  );
};

Workaround

Just add key to PagerView like key={pagesContent.toString()} but it will produce re-render Pager itself and in some cases it's not possible to use this hack

@yuri-lomashko-itechart
Copy link
Author

yuri-lomashko-itechart commented Sep 22, 2022

May be related - #518

It seems that I don't have current problem when I use solution from 27e8003 instead of 3260863

@troZee troZee added the hacktoberfest hacktoberfest label Oct 20, 2022
@jwanga
Copy link

jwanga commented Jan 11, 2023

@yuri-lomashko-itechart the key workaround solved my problem.

@Melchek
Copy link

Melchek commented Apr 4, 2023

Same for me, the key workaround solved the problem, but without the workaround the issue still exist in 6.2.0.

@yqz0203
Copy link

yqz0203 commented Apr 22, 2023

Same problem.

It works by call setPageWithoutAnimation before changing pages in my project.

 onPageSelected={e => {
            // add this
            pageViewRef.current?.setPageWithoutAnimation(1);
            const { position } = e.nativeEvent;

            if (position === 2) {
              setPages(pages.map(item => item + 1));
            } else if (position === 0) {
              setPages(pages.map(item => item - 1));
            }
          }}>

@chrisjlan89
Copy link

chrisjlan89 commented Oct 26, 2023

I am experiencing similar issues neither of the NATIVE fixes @yuri-lomashko-itechart suggested worked for me.

In the case of my app, I have a quiz that a user interacts with if new Content DIRECTLY PROCEEDS this quiz (i.e it is loaded in based on user interaction in the next slide) it breaks / blocks navigation and is the wrong (stale / previous content)

I've narrowed it down in my case to

https://github.com/callstack/react-native-pager-view/blob/master/ios/ReactNativePageView.m#L217-L233

I changed the else block here to the below code and it works for my use case but not sure this is a viable solution for the library but I'd like to commit it if it is or someone more versed on Obj-C cares to help me refactor

else {
        // If this runs on load sometimes we get stuck in state where we can't scroll
        // my assumption is trying to go to an index which doesn't exist causes
        // an error and it just kinda silently breaks.
        if(newIndex != 0){
        [self goTo:newIndex  - 1 animated:NO];
        }
        if(newIndex == 0) {
        [self goTo:newIndex + 1 animated:NO];
        }
        [self goTo:newIndex animated:NO];
    }

Working state

react-native-pager-view-dynamic-content-working-state.mov

Broken State

react-native-pager-view-dynamic-content-broken-state.mov

In my host app I am also setting animated page view's prop of scrollEnabled to false until my request resolves.

isStackedScrollingEnabled is set to true when request begins then false once request ends.

    <AnimatedPagerView
      scrollEnabled={Platform.OS === 'ios'  && typeof isStackedScrollingEnabled !== 'undefined' ? isStackedScrollingEnabled : true}

@MrRefactor
Copy link
Collaborator

Fixed in #898

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hacktoberfest hacktoberfest
Projects
None yet
Development

No branches or pull requests

7 participants