使用先前导航参数进行React导航安装,然后使用New Params

时间:2018-05-07 15:36:59

标签: javascript reactjs react-native react-navigation

我们在React Native + React Navigation应用程序中看到了一个奇怪的行为,因此我们创建了一个简单的示例来演示。

我们有2个屏幕:A和B.

在屏幕A上,有两个按钮,每个按钮都导航到屏幕B.第一个按钮传递参数id:1,第二个按钮传递id:2。

在屏幕B上,我们是控制台在render()方法和componentDidMount()方法中记录入站参数。

如果我在屏幕A上单击id为1的按钮,屏幕B上的参数输出将在render()和componentDidMount()中记录为id:1。但是,如果我然后导航回来并非常快速地单击id为2的按钮,则记录的输出首先显示为id:1,然后显示为id:2。按以下顺序:

首先点击:

渲染:1

componentDidMount:1

(然后回来,然后快速:)

第二次点击

渲染:1

渲染:2

componentDidMount:1

componentDidMount:2

以前安装的组件的幽灵似乎仍然困扰着我们的应用程序。此外,它感觉就像一个竞争条件,因为你必须快速点击召唤幽灵,慢速点击不会导致这种行为。

这是整个应用程序:



            var Renderer = new IronPdf.HtmlToPdf();
            var PDF = Renderer.StaticRenderHTMLFileAsPdf("17789.htm", new IronPdf.PdfPrintOptions() { InputEncoding = Encoding.GetEncoding("ISO-8859-2") });
            var OutputPath = "HtmlToPDF.pdf";
            PDF.SaveAs(OutputPath);
            System.Diagnostics.Process.Start(OutputPath);




这里还有一个零食:

https://snack.expo.io/@makerepeat/navigation-bugs

...和package.json:

import React from 'react'
import { View, Text, TouchableOpacity } from 'react-native'
import { StackNavigator } from 'react-navigation'
class ScreenA extends React.Component {
  render() {
    const { navigation } = this.props;
    return (      
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <TouchableOpacity style={{ marginVertical: 12, padding: 32, borderWidth: 1 }} 
          onPress={() => { navigation.navigate( 'ScreenB', { id: 1 })}}>
          <View style={{ }}><Text>Button 1</Text></View>
        </TouchableOpacity>
        <TouchableOpacity style={{ marginVertical: 12, padding: 32, borderWidth: 1 }} 
          onPress={() => { navigation.navigate( 'ScreenB', { id: 2 })}}>
          <View style={{ }}><Text>Button 2</Text></View>
        </TouchableOpacity>
      </View>
    )
  }
}
class ScreenB extends React.Component {
  componentDidMount(){
    console.log('%c componentDidMount: '+this.props.navigation.state.params.id, 'padding: 2px; background: blue; color: #fff')
  }
  render() {
    console.log('%c render: '+this.props.navigation.state.params.id, 'padding: 2px; background: green; color: #fff')
    return (   
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <TouchableOpacity style={{ padding: 16 }} onPress={() => this.props.navigation.goBack()}>
          <View style={{ }}><Text>Button</Text></View>
        </TouchableOpacity>        
      </View>
    )
  }
}
const Router = StackNavigator({
  ScreenA: { screen: ScreenA },
  ScreenB: { screen: ScreenB }
})
export default class App extends React.Component {
  render() {
    return (
      <Router />
    )
  }
}

1 个答案:

答案 0 :(得分:1)

这里的问题是navigation.navigate的工作原理。如果您在未传递下一个屏幕的密钥的情况下使用它,则react-navigation不会将其与已安装的屏幕匹配,从而安装另一个屏幕。

您可以在此处观察到的情况恰好是组件尚未卸载但导航无法知道并呈现同一组件的另一个实例的情况。

您可以通过将密钥参数传递到navigate函数来防止这种情况,如下所示:

navigation.navigate({routeName: 'ScreenB', key: 'ScreenB', params: { id: 1}})

navigation.navigate({routeName: 'ScreenB', key: 'ScreenB', params: { id: 2}})

现在StackNavigator可以检查具有相同密钥的屏幕是否已存在并阻止其安装。

相关问题