与其他(父)组件反应本机共享滚动动画事件

时间:2020-10-09 16:16:40

标签: reactjs react-native react-hooks

我正在寻找以下(标准)用例的最佳实践解决方案:

我有多个带有ScrollViews或Lists的屏幕(与react-navigation连接)。屏幕有时具有相同的标题,有时具有不同的标题。这些标题包括动画,具体取决于视图的滚动位置。在创建导航器(父视图)时,有时会安装标头,有时会在视图中对其进行修改。

所以我的问题基本上是,我该如何共享一个普通的scrollY变量

const scrollY = useRef(new Animated.Value(0)).current

与其他组件(尤其是如果它们安装在父组件中,例如Header)。另外,如果视图发生更改,如何重置此变量,或者每个屏幕都使用scrollY自己的实例?

我想要一个带有钩子的解决方案,例如:

const ParentComponent = props => (
    <MainStack.Navigator
        screenOptions={{
            header: props => <Header {...props}/>
        }}
    >
        <MainStack.Screen
            name="Screen1" 
            component={Screen1}
        />
        <MainStack.Screen
            name="Screen2" 
            component={Screen2}
        />
    </MainStack.Navigator>
)


// Similar to Screen2
const Screen1 = props => {
    // get the global?! scrollY
    const scrollY = useScrollY();
    return(
        <Animated.ScrollView
            onScroll={
                Animated.event(
                    [
                        {
                            nativeEvent: {contentOffset: {y: scrollY}}
                        }
                    ]
                )
            }
        >
        </Animated.ScrollView>
    );
}

// Header
const Header = props => {
    // get the relevant scrollY variable from Screen1 or Screen2
    const scrollY = useScrollY();
    const animation = scrollY.interpolate({...})
    return (...);
}

我有一个可行的解决方案,将scrollY放入redux,但它似乎有问题且运行缓慢。另外,我尝试在文件范围内创建全局scrollY(请注意以下内容),并使其可以通过函数进行访问。但这不是很像React。在最高组件中创建scrollY并通过props向下传递也不是真正的选择,因为实际上层次结构已经太复杂了。我想有一个简单,高效,最佳实践的解决方案来共享scrollY,最好通过一个钩子来共享。有什么想法吗?

注意:首先尝试使用文件作用域变量

let scrollY = new Animated.Value(0);
let history = {};
export const useScrollY = () => {
    const reset = useCallback(
        () => {
            scrollY = new Animated.Value(0);
        },
        []
    );
    return [scrollY, reset];
};

这里的问题是,在StackNavigator方案中,尽管滚动位置可能仍然不同,但父堆栈将重置为滚动位置0的动画。我还尝试了使用历史记录变量的方法,但那实际上没有用。

1 个答案:

答案 0 :(得分:0)

我认为您可以通过将动画值从父级传递给子级来实现。

例如:

const ParentComponent = props => {
   const [scrollY] = useState(()=> new Animated.Value(0));

   return <MainStack.Navigator
        screenOptions={{
            header: props => <Header {...props} {...{scrollY}}/>
        }}
    >
        <MainStack.Screen
            name="Screen1" 
            >
           {(props)=> <Screen1 {...props} {...{scrollY}} />}
        </MainStack.Screen>
        <MainStack.Screen
            name="Screen2" 
            component={Screen2}
        />
    </MainStack.Navigator>
)