【问题标题】:How to detect first launch in react-native如何检测 react-native 中的首次启动
【发布时间】:2016-11-21 07:57:34
【问题描述】:

检测 react-native 应用的首次启动和初始启动以显示入门/介绍屏幕的好方法是什么?

【问题讨论】:

  • 但是由于 AsyncStorage 是~async~,所以响应是通过回调返回的,我无法让视图等待。还是我错过了什么?
  • 您可以使用View 状态,假设您可以显示一些ActivityIndicator 直到LocalStorage' 响应,然后通过this.setState({shouldShowIndicator: false}) 之类的东西隐藏ActivityIndi​​cator
  • 考虑使用Realmrealm.io 我已经使用Realm 显示几个页面,仅用于首次应用启动。所以这非常完美。
  • 在清除应用数据时不会清除 asyncStorage 吗?

标签: react-native


【解决方案1】:

你的逻辑应该遵循这个:

class MyStartingComponent extends React.Component {
    constructor(){
        super();
        this.state = {firstLaunch: null};
    }
    componentDidMount(){
        AsyncStorage.getItem("alreadyLaunched").then(value => {
            if(value == null){
                 AsyncStorage.setItem('alreadyLaunched', true); // No need to wait for `setItem` to finish, although you might want to handle errors
                 this.setState({firstLaunch: true});
            }
            else{
                 this.setState({firstLaunch: false});
            }}) // Add some error handling, also you can simply do this.setState({fistLaunch: value == null})
    }
    render(){
       if(this.state.firstLaunch === null){
           return null; // This is the 'tricky' part: The query to AsyncStorage is not finished, but we have to present something to the user. Null will just render nothing, so you can also put a placeholder of some sort, but effectively the interval between the first mount and AsyncStorage retrieving your data won't be noticeable to the user.
       }else if(this.state.firstLaunch == true){
           return <FirstLaunchComponent/>
       }else{
           return <NotFirstLaunchComponent/>
       }
}

希望对你有帮助

【讨论】:

  • 对我不起作用...它每次都显示它。似乎是 AsyncStorage 的一般问题。 github.com/facebook/react-native/issues/18372
  • 问题是 true 不是字符串。用引号括起来,然后它就可以工作了
  • JSON.stringify 将所有内容放入异步存储之前。 JSON.parse 从存储中检索后
  • @martinarroyo 这种方法将导致包含此代码的应用程序更新也被“视为”为firstLaunch。我刚碰到这个问题。
  • 我收到一条使用此代码的警告:“java.lang.Boolean cannot be cast to java.lang.String”
【解决方案2】:

我对martinarroyo 的建议做了一些调整。 AsyncStorage.setItem 应该设置一个字符串值而不是布尔值。

import { AsyncStorage } from 'react-native';
    
const HAS_LAUNCHED = 'hasLaunched';

function setAppLaunched() {
  AsyncStorage.setItem(HAS_LAUNCHED, 'true');
}

export default async function checkIfFirstLaunch() {
  try {
    const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
    if (hasLaunched === null) {
      setAppLaunched();
      return true;
    }
    return false;
  } catch (error) {
    return false;
  }
}

然后可以将这个函数导入到任何你需要的地方。请注意,您应该在等待异步函数检查 AsyncStorage 时呈现 null(或其他巧妙的东西)。

import React from 'react';
import { Text } from 'react-native';
import checkIfFirstLaunch from './utils/checkIfFirstLaunch';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isFirstLaunch: false,
      hasCheckedAsyncStorage: false,
    };
  }

  async componentWillMount() {
    const isFirstLaunch = await checkIfFirstLaunch();
    this.setState({ isFirstLaunch, hasCheckedAsyncStorage: true });
  }

  render() {
    const { hasCheckedAsyncStorage, isFirstLaunch } = this.state;

    if (!hasCheckedAsyncStorage) {
      return null;
    }

    return isFirstLaunch ?
      <Text>This is the first launch</Text> :
      <Text>Has launched before</Text>
    ;
  }
}

【讨论】:

  • 为什么不使用布尔值?
  • 因为它是一个键值字符串存储,并且 AsyncStorage 文档指定该值应该是一个字符串https://facebook.github.io/react-native/docs/asyncstorage#setitem。我不是 100% 确定,但我假设如果您尝试存储布尔值,它将被转换为字符串。稍后使用getItem 获取它时,我假设它不会自动转换回布尔值。
  • 我认为在等待异步函数检查 AsyncStorage 时渲染一个聪明的事情是加载动画。
  • @Fl4v AsyncStorage 返回速度如此之快,无需加载指示器。仅仅因为它是async 并不一定意味着解决/拒绝需要很长时间:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多