React-native-navigation从另一个tabnavigator更改状态

时间:2017-10-25 10:33:28

标签: react-native react-navigation

我正在使用react-navigation / TabNavigator,有没有办法在不使用Redux或mobx的情况下从另一个标签更改标签的状态?

2 个答案:

答案 0 :(得分:4)

是的,你可以。它有点复杂,有点hacky并且可能有一些副作用,但理论上你可以做到。我创建了一个working example snack here

在反应导航中,您可以set parameters使用路线密钥查看其他屏幕。

  

当调度SetParams时,路由器将产生一个新的状态   已经改变了特定路线的参数,如密钥

所示      
      
  • params - object - required - 要合并到现有路径参数中的新参数
  •   
  • 密钥 - 字符串 - 必需 - 应获取新参数的路由密钥
  •   

示例

import { NavigationActions } from 'react-navigation'

const setParamsAction = NavigationActions.setParams({
  params: { title: 'Hello' },
  key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)

为此,您需要知道要传递参数的屏幕的key道具。现在这是我们弄乱的地方。我们可以组合onNavigationStateChangescreenProps道具来获取当前的堆栈键,然后将它们作为属性传递给我们当前的屏幕。

重要说明:因为首次启动应用时onNavigationStateChange未触发this.state.keys将是一个空数组。因此,您需要执行初始导航操作。

示例

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      keys: []
    };
  }
  onNavigationChange = (prevState, currentState) => {
    this.setState({
      keys: currentState.routes
    });
  }
  render() {
    return(
      <Navigation
        onNavigationStateChange={this.onNavigationChange}
        screenProps={{keys: this.state.keys}}
      />
    );
  }
}

现在我们可以使用keys prop获取我们需要的屏幕键,然后我们可以传递所需的参数。

class Tab1 extends Component {
  onTextPress = () => {
    if(this.props.screenProps.keys.length > 0) {
      const Tab2Key = this.props.screenProps.keys.find((key) => (key.routeName === 'Tab2')).key;
      const setParamsAction = NavigationActions.setParams({
        params: { title: 'Some Value From Tab1' },
        key: Tab2Key,
      });
      this.props.navigation.dispatch(setParamsAction);
    }
  }
  render() {
    const { params } = this.props.navigation.state;
    return(
      <View style={styles.container}>
        <Text style={styles.paragraph} onPress={this.onTextPress}>{`I'm Tab1 Component`}</Text>
      </View>
    )
  }
}

class Tab2 extends Component {
  render() {
    const { params } = this.props.navigation.state;
    return(
      <View style={styles.container}>
        <Text style={styles.paragraph}>{`I'm Tab2 Component`}</Text>
        <Text style={styles.paragraph}>{ params ? params.title : 'no-params-yet'}</Text>
      </View>
    )
  }
}

现在您可以从导航中获取新参数,您可以在屏幕中使用它,也可以在componentWillReceiveProps更新您的状态。

componentWillReceiveProps(nextProps) {
  const { params } = nextProps.navigation.state;
  if(this.props.navigation.state.params && params &&  this.props.navigation.state.params.title !== params.title) {
    this.setState({ myStateTitle: params.title});
  }
}

更新

现在,react-navigation支持可用于检测焦点或模糊屏幕状态的侦听器。

  

addListener - 订阅导航生命周期的更新

     

React Navigation将事件发送到屏幕预订的组件   它们:

     
      
  • willBlur - 屏幕将无焦点
  •   
  • willFocus - 屏幕将重点关注
  •   
  • didFocus - 屏幕聚焦(如果有转换,转换完成)​​
  •   
  • didBlur - 屏幕未聚焦(如果有转换,转换已完成)
  •   

来自文档的示例

const didBlurSubscription = this.props.navigation.addListener(
  'didBlur',
  payload => {
    console.debug('didBlur', payload);
  }
);
// Remove the listener when you are done
didBlurSubscription.remove();

// Payload
{
  action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
  context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
  lastState: undefined,
  state: undefined,
  type: 'didBlur',
};

答案 1 :(得分:2)

如果我明白你想要什么它是如何我想出刷新流行的导航屏幕。在我的例子中,我刷新了我从相机捕获的图像:

屏幕A

  onPressCamera() {
    const { navigate } = this.props.navigation;

    navigate('CameraScreen', {
      refreshImages: function (data) {
        this.setState({images: this.state.images.concat(data)});
      }.bind(this),
    });
}

屏幕B

  takePicture() {
   const {params = {}} = this.props.navigation.state;

   this.camera.capture()
     .then((data) => {
       params.refreshImages([data]);
     })
     .catch(err => console.error(err));
  }