如何解决:无法在React-Native中的已卸载组件警告上调用setState(或forceUpdate)?

问题描述 投票:1回答:2

在HomeScreen中的React-native项目中,我从AsyncStorage获取了一些值。获得此值后,我将其进行比较并决定接下来将在哪个屏幕上进行。如果getValue为null,则它将进入WelcomeScreen,如果它不为null,则它将进入HomeDrawer屏幕。

我在这里提供了代码 -

import React from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import {StackNavigator} from 'react-navigation';
import WelcomeScreen from './WelcomeScreen';
import LoginScreen from './components/LoginScreen';
import NoteMeHome from './components/NoteMeHome';
import HomeDrawer from './HomeDrawer/HomeDrawer';
import SettingsScreen from './components/SettingsScreen';

class HomeScreen extends React.Component {

  state = {
    getValue: '',

  }

  async componentDidMount() {

    const token = await AsyncStorage.getItem('toke');
    this.setState({ getValue: token });

  }

  render() {
    console.log('#ZZZ:', this.state.getValue);

    if(this.state.getValue !== null) {
      return (
        <AppStackNavigator/>
      );
    } else {
      return (
        <AppStackNavigator2/>
      );
    }

  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});


const AppStackNavigator = new StackNavigator({
  HomeDrawer: {screen:HomeDrawer},
  WelcomeScreen: {screen:WelcomeScreen},


  LoginScreen: {screen:LoginScreen},
  NoteMeHome: {screen:NoteMeHome},

  SettingsScreen: {screen:SettingsScreen}

})

const AppStackNavigator2 = new StackNavigator({
  WelcomeScreen: {screen:WelcomeScreen},
  HomeDrawer: {screen:HomeDrawer},

  LoginScreen: {screen:LoginScreen},
  NoteMeHome: {screen:NoteMeHome},

  SettingsScreen: {screen:SettingsScreen}

})

export default HomeScreen;

现在,在运行之后,如果我在变量getValue中得到空值,那么它显示以下警告 -

警告:无法在卸载的组件上调用setState(或forceUpdate)。这是一个无操作,但它表示应用程序中存在内存泄漏。要修复,请取消componentWillUnmount方法中的所有订阅和异步任务。

那么,我该如何解决这个警告问题呢?

javascript react-native react-navigation
2个回答
1
投票

我不知道这是不是一个好习惯。问题是 - 我的组件用空字符串初始化,我在渲染函数中检查null。使用null初始化getvalue或在render中检查空字符串将解决此问题。

所以,我在代码中所做的更改是 -

state = {
    getValue: ''

  }

它删除了警告。


0
投票

更好的解决方案是使用来自SwitchNavigatorreact-navigation,因为您的导航堆栈是相同的,并且您只想基于该令牌路由到第一个屏幕。

see example

import React from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import {StackNavigator, createSwitchNavigator} from 'react-navigation';
import WelcomeScreen from './WelcomeScreen';
import LoginScreen from './components/LoginScreen';
import NoteMeHome from './components/NoteMeHome';
import HomeDrawer from './HomeDrawer/HomeDrawer';
import SettingsScreen from './components/SettingsScreen';

const AppStackNavigator = new StackNavigator({
  HomeDrawer: {screen:HomeDrawer},
  LoginScreen: {screen:LoginScreen},
  NoteMeHome: {screen:NoteMeHome},
  SettingsScreen: {screen:SettingsScreen}
});

export default createAppContainer(createSwitchNavigator(
  {
    LaunchScreen,
    WelcomeScreen,
    AppStackNavigator,
  },
  {
    initialRouteName: 'LaunchScreen',
  }
));

class LaunchScreen extends React.Component {
  constructor(props) {
    super(props);
    this._getToken();
  }

  // Fetch the token from storage then navigate to the appropriate place
  _getToken = async () => {
    const tok = await AsyncStorage.getItem('toke');

    // This will switch to the Welcome screen or main AppStack. Then this launch
    // screen will be unmounted and thrown away.
    this.props.navigation.navigate(tok ? 'AppStackNavigator' : 'WelcomeScreen');
  };

  // Render any loading content that you like here
  render() {
    return (
      <View>
        {/*...*/}
      </View>
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.