在动画场景之外控制 StackNavigator

Control StackNavigator outside of the animated scene

编辑:我了解我的问题和解决方案,所以我重新表述我的问题,然后给出答案。

正常 StackNavigator 和带导航的屏幕如下所示:

class ExampleScreen extends React.Component {
  render() {
    const { navigate, state } = this.props.navigation.navigate;
    const exampleTitle = state.params.title;

    return (
      <View>
        <Text>{exampleTitle}</Text>
        <Button
          title="Click"
          onPress={() => {
            navigate('Example', { exampleTitle: 'foo' })
          }}
        />
      </View>
    );
  }
}

const ExampleNavigator = StackNavigator({
  Example: { screen: ExampleScreen }
}, {
  initialRouteName: 'Example',
  initialRouteParams: { exampleTitle: 'bar' }
});

AppRegistry.registerComponent('Example', () => ExampleNavigator);

我想访问 ExampleScreen#render 之外的 navigation 对象,这样它就不是 CardStack 动画的一部分。

我通过添加另一个屏幕来渲染解决了我的问题 ExampleNavigator 并且 在 ExampleNavigator 上设置 ref 属性。 navigation 对象和 路由参数的访问方式略有不同,但我将在下面的注释中解释整个代码。

class ExampleScreen extends React.Component {
  render() {
    const { state } = this.props.navigation.navigate;
    const exampleTitle = state.params.title;

    return (
      <View>
        <Text>{exampleTitle}</Text>
      </View>
    );
  }
}

const ExampleNavigator = StackNavigator({
  Example: { screen: ExampleScreen }
}, {
  initialRouteName: 'Example',
  initialRouteParams: { exampleTitle: 'bar' }
});

// my solution
class RootScreen extends React.Component {
  constructor(props) {
    super(props);
    // makes sure _onPress has the correct context when clicked
    this._onPress = this._onPress.bind(this);
  }
  render() {
    // flex: 1 is set to make the navigator visible. you wont see the navigator
    // without this.
    return (
      <View style={{flex: 1}}>
        <ExampleNavigator ref='nav' />
        <Button title='Click' onPress={this._onPress} />
      </View>
    );
  }

  _onPress() {
    // read navigate and state from _navigation
    const { navigate, state } = this.refs.nav._navigation;
    const { routes, index } = state;
    // read scene params through the route of the index passed in state
    const params = routes[index].params;
    const exampleTitle = params.exampleTitle + ' clicked';

    // use the navigate method as your normally would
    navigate('Example', {exampleTitle});
  }
}

AppRegistry.registerComponent('Example', () => RootScreen);

我相信我想做的事情与此非常相似,即使不完全相同。我不明白为什么这不是很常见(从组件中提取行为并允许更高级别的组件定义一组组件的行为,在这种情况下定义所有导航行为)而无需使用 refs .

一个理想的解决方案似乎是:

class ExampleScreen extends React.Component {
  render() {
    const { navigate, state } = this.props.navigation.navigate;
    const exampleTitle = state.params.title;

    return (
      <View>
        <Text>{exampleTitle}</Text>
        <Button
          title="Click"
          onPress=state.params.onPress
        />
      </View>
    );
  }
}

const ExampleNavigator = StackNavigator({
  Example: { screen: ExampleScreen }
}, {
  initialRouteName: 'Example',
  initialRouteParams: {
    exampleTitle: 'bar',
    onPress: () => {XXX.navigate('Example', { exampleTitle: 'foo' })}
  }
});

AppRegistry.registerComponent('Example', () => ExampleNavigator);

导航以某种方式在 StackNavigator initialRouteParams 中可用。

我是否还遗漏了一些似乎普遍预期的设计模式的简单解决方案?