如何根据前一个道具渲染屏幕?

How to render a screen based on the props from the previous one?

我正在创建一个应用程序,其中有一个屏幕 (SpotMapScreen),根据所选 'tab',我在该屏幕上显示地图或列表视图上的“地点”。用户可以通过单击顶部选项卡之一更改显示系统:

我还想让用户可以通过单击上一个屏幕(开始屏幕)中的适当按钮来打开某个选项卡:

因此,当用户单击上述按钮之一并打开下一个屏幕 (SpotMapScreen) 时,我将传递参数 'active':

                <TouchableOpacity
              style={styles.button}
              onPress={() => this.props.navigation.navigate('SpotMap', { active: 'map' })}
            >
              <Image style={[styles.sportIcon]}
                     source={require('../assets/images/ic_choose_relation.png')}/>
              <Text
                style={styles.buttonText}>{translate('startAct.btn_map')}</Text>
            </TouchableOpacity>
            <View style={styles.verticalDivision}/>
            <TouchableOpacity
              style={styles.button}
              onPress={() => this.props.navigation.navigate('SpotMap', { active: 'list' })}
            >
              <Image style={[styles.sportIcon]}
                     source={require('../assets/images/ic_choose_organized.png')}/>
              <Text
                style={styles.buttonText}>{translate('startAct.btn_list')}</Text>
            </TouchableOpacity>

在 SpotMapScreen 上,我从构造函数中的道具获取此参数:

  constructor(props) {
super(props)
this.mapSupplier = new MapSupplier()
this.mapSupplier.setMyLocation(mock.myLocation)
this.state = {
  myLocation: mock.myLocation,
  active: props.navigation.state.params.active,
  filters: {},
  spots: [],
  addNewSpotModeEnabled: true,
  newSpotMarker: null,
}

}

我正在根据这个 'active' 变量渲染整个屏幕:

  render() {
const active = this.state.active
if (active === 'map') {
  return (
    <SafeAreaView style={styles.container}>
      {this.renderTabs(active)}
      {this.renderMap()}
      {this.renderActionButton()}
    </SafeAreaView>
  )
} else {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView>
        {this.renderTabs(active)}
        {this.renderList()}
      </ScrollView>
    </SafeAreaView>
  )
}

} }

并且用户可以通过单击特定选项卡来更改显示外观:

      handleTab = (tabKey) => {
    this.setState({ active: tabKey })
  }

  renderTabs(active) {
    const openMenu = () => {
      this.props.navigation.openDrawer()
    }
    return (
      <SafeAreaView style={styles.tabs}>
        <View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
          <MaterialIcons name='menu' onPress={openMenu} size={18} style={{ alignSelf: 'center', paddingBottom: 10 }}/>
        </View>
        <View style={[styles.tab, active === 'map' ? styles.activeTab : null]}>
          <Feather name="map-pin" color={colors.black} size={18}
                   style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
          <Text style={[styles.tabTitle, active === 'map' ? styles.activeTabTitle : null]}
                onPress={() => this.handleTab('map')}>
            {translate('mapAct.map')}
          </Text>
        </View>
        <View style={[styles.tab, active === 'list' ? styles.activeTab : null]}>
          <Feather name="list" color={colors.black} size={18}
                   style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
          <Text style={[styles.tabTitle, active === 'list' ? styles.activeTabTitle : null]}
                onPress={() => this.handleTab('list')}>
            {translate('mapAct.list')}
          </Text>
        </View>
        <View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
          <MaterialIcons name='filter-list' onPress={() => this.props.navigation.navigate('Filters')} size={18}
                         style={{ alignSelf: 'center', paddingBottom: 10 }}/>
        </View>
      </SafeAreaView>
    )
  }

但这是我的问题,此解决方案仅适用于首次使用屏幕。当用户返回 StartScreen 并单击其中一个按钮时,不会调用下一个屏幕 (SpotMap) 中的构造函数,因此不会打开正确的选项卡。

我如何才能在每次打开下一个屏幕时从 StartScreen 接收道具,而不仅仅是第一次(更像是 android OnResume() 而不是 OnCreate())。我读到我可以使用 componentDidMount() 方法,但它对我不起作用,可能是因为我使用的是 async componentDidMount() 方法版本?

非常感谢你的帮助。

我发布了我自己问题的解决方案,因为我终于找到了。如果你想在每次“恢复”屏幕并且你正在使用 async componentDidMount() 时以 react-native 从上一个屏幕获取道具,你应该重写方法 componentDidUpdate(prevProps, prevState)。我将下面的代码添加到“SpotMapScreen”,现在它在我的问题中按预期工作:

    componentDidUpdate(prevProps, prevState) {
    let new_active = 'map'
    if (typeof this.props.navigation.state.params != "undefined"){
      new_active = this.props.navigation.state.params.active
    }

    if (prevState.active !== new_active) {
      this.setState({
        active: new_active,
      })
    }
  }