leecade / react-native-swiper

The best Swiper component for React Native.
MIT License
10.37k stars 2.35k forks source link

Struggling to get up to date view on swiper/stale view on swiper #1157

Open CDBridger opened 4 years ago

CDBridger commented 4 years ago

Which OS ?

Android

Version

Which versions are you using:

Expected behaviour

see most up to date state of child view in swiper

Actual behaviour

child view doesn't update

Steps to reproduce

  1. Install react navigation + swiper
  2. use tab navigator, put swiper as a tab
  3. set swiper tab as initial tab
  4. see swiper child views fine with initial state
  5. navigate to different tab
  6. navigate to swiper tab with params which swiper passes to child views
  7. see that child views haven't updated
CDBridger commented 4 years ago

Here is my code if this helps, the reason I put initial state in useEffect was because I noticed the function to get initial state was getting called multiple times which I didn't want.

type ArticleDictionary = { [idx: number]: IArticle | undefined }

const articleAmount = 5;

const ArticleWrapper: React.FC<INavigation> = (props) => {

    const articleService = useContext(ArticleContext);
    const tabControlService = useContext(TabControlContext);
    const article = props.route.params.article as string;
    const prevArticle = useRef('');
    const swiper = useRef<Swiper | null>();
    const [articles, setArticles] = useState<ArticleDictionary>([]);
    const [currentIndex, setCurrentIndex] = useState(0);

    const focused = useIsFocused();

    useEffect(() => {
        setArticles(articleService.getArticles(0, 5)?.reduce((dict: ArticleDictionary, item: IArticle | undefined, index: number) => ({ ...dict, [index]: item }), {}));
    }, [])

    const indexChanged = useCallback((index: number) => {
        setCurrentIndex(index);
        if (focused) {
            let articleAfterNext = articleService.getArticle(articles[(index + 1).mod(articleAmount)]?.nextGuid) ?? articleService.getFirst();
            let articleBeforePrev = articleService.getArticle(articles[(index - 1).mod(articleAmount)]?.prevGuid) ?? articleService.getLast();
            setArticles({ ...articles, [(index + 2).mod(articleAmount)]: articleAfterNext, [(index - 2).mod(articleAmount)]: articleBeforePrev });
        }
    }, [articles, focused, articleService]);

    useFocusEffect(
        React.useCallback(() => {
            if (article != prevArticle.current) {
                tabControlService.close();
                setArticles({
                    ...articles,
                    [currentIndex]: articleService.getArticle(article),
                    [(currentIndex + 1).mod(articleAmount)]: articleService.getNext(article),
                    [(currentIndex - 1).mod(articleAmount)]: articleService.getPrevious(article)
                });
            }
            prevArticle.current = article;
        }, [currentIndex, article, articleService])
    );

    return (
        <Swiper style={styles.wrapper}
            ref={(ref) => swiper.current = ref}
            showsButtons={false}
            horizontal={false}
            loop={true}
            onIndexChanged={indexChanged}
            showsPagination={false}
            loadMinimal={true}
            loadMinimalSize={1}>
            <Article customkey={0} article={articles[0]} />
            <Article customkey={1} article={articles[1]} />
            <Article customkey={2} article={articles[2]} />
            <Article customkey={3} article={articles[3]} />
            <Article customkey={4} article={articles[4]} />
        </Swiper>
    )
}

export default ArticleWrapper;

const styles = StyleSheet.create({
    wrapper: {},
})