IjzerenHein / react-navigation-shared-element

React Navigation bindings for react-native-shared-element 💫
https://github.com/IjzerenHein/react-native-shared-element
MIT License
1.27k stars 124 forks source link

[HELP NEEDED] SharedElement Transition does not work properly if you map an array which uses same Component #148

Closed borstessi closed 3 years ago

borstessi commented 3 years ago

Initial situation: We have several screens with questions that are to be displayed one after the other. A SharedElement Transition is to take place when the first question is called up and also when the questions are called up.

To implement the whole thing, an array of questions is mapped - where each question results in a screen at the end, which receives the Ids of the SharedElements via the IntitalParams.

const questions = [
    {
        id: 'question-screen1',
        initial: true,
        nextId: 'question-screen2',
        index: 0,
        question: 'Are you a programmer?',
    },
    {
        id: 'question-screen2',
        initial: false,
        nextId: 'question-screen3',
        index: 1,
        question: 'Do you like GitHub?',
    },
    {
        id: 'question-screen3',
        initial: false,
        nextId: 'question-screen4',
        index: 2,
        question: 'Do you like sheep?',
    },
    {
        id: 'question-screen4',
        initial: false,
        nextId: 'Profile',
        index: 3,
        question: 'Do you like potatoes?',
    },
];

This is the array and the rough structure of a question we use.

here comes the mapping:

{questions.map((item) => {
                    return (
                        <Stack.Screen
                            {...this.props}
                            name={item.id}
                            component={Questions}
                            initialParams={{
                                id: item.id,
                                nextId: item.nextId,
                                initial: item.initial,
                                index: item.index,
                                question: item.question,
                            }}
                            sharedElementsConfig={(route, otherRoute, showing) => {
                                return [
                                    {
                                        id: item.id,
                                        animation: 'fade-in',
                                        resize: 'clip',
                                    },
                                ];
                            }}
                            options={{
                                gestureEnabled: false,
                                transitionSpec: {
                                    open: { animation: 'timing', config: { duration: 300 } },
                                    close: { animation: 'timing', config: { duration: 300 } },
                                },
                                cardStyleInterpolator: forFade,
                            }}
                        />
                    );
                })}

This is the button that opens the first screen with the first question:

<ButtonElementWithSharedTransition
            id={'question-screen1'}
            size={'large'}
            badgeCount={3}
            style={classes.marginTop}
            onPress={() => navigation.navigate('question-screen1')}>
            You got new questions!
</ButtonElementWithSharedTransition>

Then we got the Code for the SharedElement which is in this case the background:

<SharedElement id={route.params.id}>
                <View
                    style={{
                        position: 'absolute',
                        width: responsiveWidth(200),
                        height: responsiveHeight(200),
                        left: -responsiveWidth(50),
                        top: -responsiveHeight(50),
                        backgroundColor: handleBackgroundColor(),
                    }}
                />
 </SharedElement>

And last but not least we got the a SharedElementButton with transitions into the next screen:

 <CircleButtonForSharedElementTransition
                    id={props.route.params.nextId}
                    activeColor={handleButtonColor()}
                    activeIconColor={handleButtonIconColor()}
                    disabledColor={colors.inactivePrimaryMain}
                    disabledIconColor={colors.inactivePrimaryText}
                    disabled={!_.isNumber(questionAnswer)}
                    onPress={handleNext}
                />

Here is a short video of the behaving i get:

https://user-images.githubusercontent.com/17229407/109650696-dd4e4000-7b5d-11eb-8bf5-57849a9ee01b.mov

As you can see there is only one shared element transition. For me this is very odd because we are using the same code base for all the screens, so why is there one transition working while the others do not.

If i add the screens one by one without the mapping it works perfectly fine.