首页 > 解决方案 > React Native DrawerLayout:动画子导致无限递归

问题描述

ExpoGestureHandler.DrawerLayout支持根据AnimatedInterpolation提供给该renderNavigationView方法的方法对抽屉的内容进行动画处理。但是,我想为主视图而不是抽屉设置动画,所以在我的renderNavigationView方法中,我抓取了该值并将其放入组件的状态,然后尝试在组件的render方法中使用它。

这是一个最小的示例项目来说明我的意思:

https://github.com/brettdh/drawer-resize-child

这是主要的App组成部分:

import React from 'react';
import { Dimensions, StyleSheet, Text, View, Button } from 'react-native';
import { GestureHandler } from 'expo';

const { DrawerLayout } = GestureHandler;

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      progressValue: null,
    };
  }

  getAnimatedStyles() {
    const margin =
      this.state.progressValue
        ? this.state.progressValue.interpolate({
          inputRange: [0, 1],
          outputRange: [0, 30],
        })
        : 0;
    return {
      paddingVertical: margin,
    }
  }

  renderDrawer(progressValue) {
    if (!this.state.progressValue) {
      this.setState({ progressValue });
    }

    return (
      <View style={styles.drawer}>
        <Text>Drawer content</Text>
      </View>
    );
  }

  render() {
    return (
      <DrawerLayout
        ref={drawer => {this.drawer = drawer;}}
        renderNavigationView={(pv) => this.renderDrawer(pv)}
        drawerWidth={Dimensions.get('window').width * 0.75}
        drawerType="back"
        overlayColor="#00000000"
      >
        <View style={[styles.container, this.getAnimatedStyles()]}>
          <Button onPress={() => this.drawer.openDrawer()} title="Open drawer"/>
        </View>
      </DrawerLayout>
    );
  }
}

const styles = StyleSheet.create({
  drawer: {
    flex: 1,
    backgroundColor: '#F95A570C',
    alignItems: 'center',
    justifyContent: 'center',
  },
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

当我运行这个项目(yarn && yarn start,按i)时,我在 iOS 模拟器中得到了这个:

non-std C++ exception

ABI26_0_0RCTFatal
-[ABI26_0_0RCTCxxBridge handleError:]
__43-[ABI26_0_0RCTCxxBridge _initializeBridge:]_block_invoke
facebook::ReactABI26_0_0::ABI26_0_0RCTMessageThread::tryFunc(std::__1::function<void ()> const&)
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__
__CFRunLoopDoBlocks
__CFRunLoopRun
CFRunLoopRunSpecific
+[ABI26_0_0RCTCxxBridge runRunLoop]
__NSThread__start__
_pthread_body
_pthread_body
thread_start

这在 React Native Debugger 中:

RangeError: Maximum call stack size exceeded

This error is located at:
    in RCTView (at View.js:78)
    in View (at App.js:49)
    in RCTView (at View.js:78)
    in View (at createAnimatedComponent.js:147)
    in AnimatedComponent (at DrawerLayout.js:378)
    in RCTView (at View.js:78)
    in View (at createAnimatedComponent.js:147)
    in AnimatedComponent (at DrawerLayout.js:377)
    in Handler (at DrawerLayout.js:425)
    in DrawerLayout (at App.js:42)
    in App (at registerRootComponent.js:35)
    in RootErrorBoundary (at registerRootComponent.js:34)
    in ExpoRootComponent (at renderApplication.js:35)
    in RCTView (at View.js:78)
    in View (at AppContainer.js:102)
    in RCTView (at View.js:78)
    in View (at AppContainer.js:122)
    in AppContainer (at renderApplication.js:34)

这些错误发生在导致我的应用程序崩溃的错误之前:

Warning: Cannot update during an existing state transition (such as within 
`render` or another component's constructor). Render methods should be a pure 
function of props and state; constructor side-effects are an anti-pattern, but
can be moved to `componentWillMount`.

(我想在 期间避免这种setState情况render(),但我不确定如何。这可能是一个 react-native-gesture-handler 功能请求,DrawerLayout将一个progressValueprop 注入到它的子组件中。)

Warning: Failed prop type: Invalid prop `paddingVertical` supplied to `View`.
Bad object: {
  "flex": 1,
  "backgroundColor": "#fff",
  "alignItems": "center",
  "justifyContent": "center",
  "paddingVertical": 0
}
    in View (at App.js:49)
    in App (at registerRootComponent.js:35)
    in RootErrorBoundary (at registerRootComponent.js:34)
    in ExpoRootComponent (at renderApplication.js:35)
    in RCTView (at View.js:78)
    in View (at AppContainer.js:102)
    in RCTView (at View.js:78)
    in View (at AppContainer.js:122)
    in AppContainer (at renderApplication.js:34)

另外:我觉得这也值得一个错误报告,但我不知道这是否是 React Native、Expo 或 react-native-gesture-handler 的问题。

标签: reactjsreact-nativeexpo

解决方案


尝试Animated从 React-Native 使用。更改ViewAnimated.View。使用Animated.timing函数的回调来设置您的状态。


推荐阅读