HubertRyanOfficial / between-pages

A library to help you animate and improve the user experience when is moved between pages with animations on react native apps.
29 stars 1 forks source link

Fails when the second page is using a global context #3

Open amalthomas-exe opened 11 months ago

amalthomas-exe commented 11 months ago

In my project, the second screen is fetching the data from a context. There are no issues if I go to the second screen using: navigation.navigate()

However, if I use the BetweenPages animation, the app crashes with the message: ERROR TypeError: Cannot read property '<context name>' of undefined

From my investigation, it seems as if the transition is failing to use the useContext hook.

Please look into it @HubertRyanOfficial .

HubertRyanOfficial commented 11 months ago

Hey @amalthomas-exe , I'm here to help you!

Can you show a little of your code or something else?

amalthomas-exe commented 11 months ago

Sure!

Newscard.js

import React, { useEffect, useState,useContext } from 'react'
import { View, StyleSheet, Text, Dimensions, Animated, Image, Alert } from 'react-native'
import AuthorInfo from './AuthorInfo'
import Icon from 'react-native-vector-icons/FontAwesome'
import { PanGestureHandler, State, TapGestureHandler } from 'react-native-gesture-handler'
import FullPageNews from '../pages/FullPageNews/FullPageNews'
import {useBetweenPages,BetweenTypes} from 'between-pages'
import newsContext from '../context/newsContext'
const ScreenWidth = Dimensions.get("window").width

//edit the function below to include only a certain count of characters to the string

function reduceStringToWordCount(inputString, wordCount) {
    const wordsArray = inputString.trim().split(/\s+/);
    const reducedWordsArray = wordsArray.slice(0, wordCount);
    const reducedString = reducedWordsArray.join(" ");
    return reducedString;
}

function reduceStringToCharacterCount(inputString, charCount) {
    if (inputString.length <= charCount) {
        return inputString;
    } else {
        const reducedString = inputString.slice(0, charCount);
        return reducedString;
    }
}

const Newscard = (props) => {
    const translateX = new Animated.Value(0);
    const [isDragging, setIsDragging] = React.useState(false);
    const [liked, setLiked] = useState(false);
    const [bookmarked, setBookmarked] = useState(false);
    const doubleTapRef = React.useRef(null);
    const context = useContext(newsContext);
    const {startTransition} = useBetweenPages(<FullPageNews context={context}/>)

    const handleToNewsPage = () => {
        startTransition(
            {
                type:BetweenTypes.SPRING,
                duration: 300,
                endAnimation:true
            },
            ()=>{
                props.navigation.navigate("FullPageNews");
            }
        );
    }

    return (
        ((props.index == props.currentItem) || (props.index == props.currentItem + 1)) &&
        <PanGestureHandler
            enabled={props.index == props.currentItem}
            maxPointers={1}
            onGestureEvent={
                Animated.event(
                    [
                        {
                            nativeEvent: {
                                translationX: translateX,
                            },
                        },
                    ],
                    {
                        useNativeDriver: true,
                    }
                )
            }

            onHandlerStateChange={(e) => {
                if (e.nativeEvent.state === State.BEGAN) {
                    setIsDragging(true);
                }

                if (e.nativeEvent.state === State.ACTIVE) {
                    console.log("done")

                }
                if (e.nativeEvent.state === State.END) {
                    console.log("end")
                    setIsDragging(false);
                    if (e.nativeEvent.translationX < -50) {
                        props.setActiveIndex(props.currentItem + 1);
                    }
                    else if (e.nativeEvent.translationX > 50) {
                        props.setActiveIndex(props.currentItem - 1);
                    }
                }
            }}

        >
            <Animated.View style={{
                backgroundColor: props.color,
                paddingHorizontal: 25,
                paddingBottom: 10,
                paddingTop: 20,
                width: ScreenWidth/1.15,
                //height:Dimensions.get("window").height/2.1,
                marginBottom: 20,
                borderRadius: 25,
                display: 'flex',
                flexDirection: 'column',
                position: 'absolute',
                zIndex: props.zIndex,
                left: "-42%",
                transform: [
                    { translateX: (isDragging) ? translateX : props.animationProps[0] },
                    { rotate: props.animationProps[1] },
                    { translateY: props.animationProps[2] },
                ],
                opacity: props.animationProps[3],
            }
            }>
                <TapGestureHandler
                    onHandlerStateChange={(e) => {
                        if (e.nativeEvent.state === State.ACTIVE) {
                            //props.navigation.navigate("FullPageNews");
                            handleToNewsPage();
                        }
                    }
                    }

                    waitFor={doubleTapRef}
                >
                    <TapGestureHandler
                        numberOfTaps={2}
                        ref={doubleTapRef}
                        onHandlerStateChange={(e) => {
                            if (e.nativeEvent.state === State.ACTIVE) {
                                setLiked(!liked);
                            }
                        }
                    }
                    >
                    <View>
                        <Text style={{
                            fontFamily: "Manrope-Bold",
                            color: "black",
                            fontSize: 30,
                            lineHeight: 40
                        }}>
                            {(props.news.description !== null) ? reduceStringToWordCount(props.news.title, 10) + "..." : props.news.title}
                        </Text>
                        <Text style={{
                            marginTop: 20,
                            fontFamily: "Manrope-Regular",
                            color: "#0000008e",
                            fontSize: 15,
                        }}>
                            {props.news.publishedAt.split("T")[0]}
                        </Text>
                        <View>
                            <AuthorInfo author={props.news.source.name} reduceStringToCharacterCount={reduceStringToCharacterCount} />
                        </View>
                        {!(props.news.description === null || props.news.description == "") && <View style={{
                            marginTop: 20
                        }}>
                            <Text style={{
                                color: 'black',
                                fontSize: 15,
                                fontFamily: "Manrope-Medium",

                                lineHeight: 25
                            }}>
                                {reduceStringToWordCount(props.news.description, 30) + "..."}
                            </Text>
                        </View>}

                        <View style={{
                            marginTop: 50
                        }}>
                            <View style={{
                                position: 'relative',
                                alignSelf: "flex-end",
                                display: 'flex',
                                flexDirection: 'row'
                            }}>
                                <TapGestureHandler
                                    onHandlerStateChange={(e) => {
                                        if (e.nativeEvent.state === State.ACTIVE) {
                                            setLiked(!liked);
                                        }
                                    }
                                    }
                                >
                                    <View style={styles.actionButtons}>
                                        <Icon name={liked ? "thumbs-up" : "thumbs-o-up"} size={18} color="black" />
                                    </View>
                                </TapGestureHandler>

                                <TapGestureHandler
                                    onHandlerStateChange={(e) => {
                                        if (e.nativeEvent.state === State.ACTIVE) {
                                            setBookmarked(!bookmarked);
                                        }
                                    }
                                    }
                                >
                                <View style={styles.actionButtons}>
                                    <Icon name={bookmarked ? "bookmark" : "bookmark-o"} size={18} color="black" />
                                </View>
                                </TapGestureHandler>

                                <View style={styles.actionButtons}>
                                    <Icon name="share-square-o" size={18} color="black" />
                                </View>
                            </View>
                        </View>
                    </View>
                    </TapGestureHandler>
                </TapGestureHandler>
            </Animated.View>
            {/* </FlingGestureHandler> */}
        </PanGestureHandler>
    );
}

const styles = StyleSheet.create({
    actionButtons: {
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        borderWidth: 0.5,
        borderColor: 'black',
        borderStyle: 'solid',
        borderRadius: 50,
        width: 30,
        height: 30,
        marginLeft: 10
    }
})
export default Newscard

FullPageNews.js

import React, { useContext } from 'react'
import { View, Text, StatusBar, Image, ScrollView } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialIcons'
import newsContext from '../../context/newsContext'
import AuthorInfo from '../../components/AuthorInfo'

const FullPageNews = (props) => {
  const { currentItem, colors, news } = useContext(newsContext)

  console.log(news[currentItem])
  return (
    <>
      <StatusBar backgroundColor={colors[currentItem % 3]} barStyle={'dark-content'} />
      <View style={{
        width: '100%',
        height: '100%',
        backgroundColor: colors[currentItem % 3],
        flexDirection: 'column',
        paddingLeft: 20,
        paddingRight: 20,
        paddingTop: 20,
      }
      }>
        <View style={{
          alignSelf: 'flex-start',
          padding: 10,
          borderRadius: 50,
          backgroundColor: "#0000002c"
        }}>
          <Icon name="arrow-back" size={35} color="black" onPress={() => props.navigation.goBack()} />
        </View>
        <ScrollView showsVerticalScrollIndicator={false}>
          <View style={{
            marginTop: 20,
          }}>
            <Text style={{
              fontFamily: "Manrope-Bold",
              color: "black",
              fontSize: 25,
              lineHeight: 40
            }}>
              {news[currentItem].title}
            </Text>
          </View>
          <View>
            <Text style={{
              marginTop: 20,
              fontFamily: "Manrope-Regular",
              color: "#0000008e",
              fontSize: 15,
            }}>
              {news[currentItem].publishedAt.split("T")[0]}
            </Text>
          </View>
          <AuthorInfo author={news[currentItem].source.name} />
          <Text style={{
            color: 'black',
            fontSize: 15,
            fontFamily: "Manrope-Medium",
            lineHeight: 25,
            marginTop: 20
          }}>
            {news[currentItem].description}
          </Text>
          <Image
            source={{ uri: news[currentItem].urlToImage }}

            style={{
              width: '100%',
              height: 300,
              marginTop: 20,
              borderRadius: 10
            }}

          >

          </Image>
          <Text style={{
            color: 'black',
            fontSize: 15,
            fontFamily: "Manrope-Medium",
            lineHeight: 25,
            marginTop: 20
          }}>
            {news[currentItem].content}
          </Text>
        </ScrollView>
      </View>
    </>
  )
}

export default FullPageNews

Hope this helps!