addListeners время от времени не работает - React нативная навигация по вкладкам

Я использовал навигацию по вкладкам реактивной навигации. Мне нужно вызывать функцию loadData в componentDidMount каждый раз, когда нажимается вкладка. Поэтому я использую в нем addListener. Но проблема в том, что для отображения данных требуется слишком много времени. Иногда он работает без проблем, а иногда показывает только загрузку данных... все время. Правильно ли я использую addListener? Заранее спасибо.

Home.js

state = {
  storageCheck: true
};

componentDidMount() {
    this._unsubscribe = this.props.navigation.addListener('willFocus', () => {
      this.loadData();
    });
}

componentWillUnmount() {
    this._unsubscribe.remove();
}

loadData = () => {
    this.setState({
        storageCheck: false
    })
}

render() {
if (this.state.storageCheck) {
  return <View>
    <Text>Loading Data...</Text>
  </View>
}
return (
    <View>
        <Text>Data</Text>
    </View>
)}

Навигация по вкладкам

const TabNavigator = createBottomTabNavigator({
  Home: {
    screen: Home
  },
  Profile: {
    screen: Profile,
    navigationOptions: ({ navigation }) => ({
      // title: 'Profile',
    })
  },
  Setting: {
    screen: Setting,
  }
},
  {
    defaultNavigationOptions: ({ navigation }) => ({
      tabBarIcon: ({ focused, tintColor }) => {
        const { routeName } = navigation.state;
        let iconName;
        if (routeName === 'Home') {
          iconName = 'home';
        } else if (routeName === 'Profile') {
          iconName = 'account-circle';
        } else if (routeName === 'Setting') {
          iconName = 'settings';
        }

        return <MaterialIcons name={iconName} size={28} color={tintColor} />;
      },
    })
  }
);

export default createAppContainer(TabNavigator);

person Amrita Stha    schedule 16.05.2020    source источник


Ответы (2)


В реакции-навигации v4.

Вы можете использовать функции await-async.

state = {
  storageCheck: true,
  loader: true,
  someData: null
};

componentDidMount() {
    this._unsubscribe = this.props.navigation.addListener('willFocus', () => {
      this.loadData();
    });
}

componentWillUnmount() {
    this._unsubscribe.remove();
}

loadData = async() => {
    this.setState({
        someData: await AsyncStorage.getItem("SOME_KEY"),
        storageCheck: false,
        loader: false
    })
}

render() {
  return (
      <View>
       {this.state.someData ? (
        <Text>data is loaded</Text>
       ) : (
        <Text> loading ... </Text>
       )}
      </View>
  )
}

ваше здоровье!

person Eftal Yurtseven    schedule 17.05.2020

Это четкое решение. Я думаю, вы можете использовать хуки и функциональный компонент. Я использую решение, связанное с этим

import React, { useState, useEffect } from "react";
import { 
    View,
    Text,
    ActivityIndicator
} from "react-native";
import { useIsFocused } from "@react-navigation/native";

const TestComp = () => {

    const [storageCheck, setStorageCheck] = useState(false);
    const [isLoaded, setIsLoaded] = useState(false);
    const isFocused = useIsFocused();

    useEffect(() => {
        const loadData = async() => {
            setStorageCheck(true);
            setIsLoaded(true);
        }
        loadData();
    }, [isFocused])


    return(
        <>
            {isLoaded ? (
                <View>
                    <Text>some data or texts..</Text>
                </View>
            ) : (
                <ActivityIndicator />
            )}
        </>
    )
}
export default TestComp;

ваше здоровье!

person Eftal Yurtseven    schedule 16.05.2020
comment
У меня есть старый проект, поэтому я не могу изменить его сейчас. И я использовал реагирующую навигацию v4. - person Amrita Stha; 16.05.2020
comment
Для v4 вы должны использовать компонент NavigationEvents. <NavigationEvents onWillFocus={() => this.fetchData()} { // enter page component container } </NavigationEvents> документы: NavigationEvents - person Eftal Yurtseven; 16.05.2020
comment
Я также пробовал navigationEvents. Но мне нужно получить данные из асинхронного хранилища, из-за чего макет мигает на миллисекунду, прежде чем отображать реальные данные. Поэтому я перешел на addListener. - person Amrita Stha; 16.05.2020
comment
Вы пробовали это? loadData = async() => { this.setState({ key: await AsyncStorage.getItem("SOMEKEY"), loader: false }); } В функции рендеринга: render(){ this.state.loader ? ( <ActivityIndicator /> ) : ( <View /> ) } - person Eftal Yurtseven; 16.05.2020
comment
tysm Eftal... ты спас меня. Использование await в setState прекрасно работает. Пожалуйста, включите эту строку в ответ, и я приму ответ. - person Amrita Stha; 17.05.2020