【问题标题】:React Native: How to prevent state reset when changing screens?React Native:换屏时如何防止状态重置?
【发布时间】:2020-11-12 13:15:36
【问题描述】:

在用户访问卡片后切换屏幕时遇到问题。每当客户端访问卡片、更改屏幕并返回到之前的相同组件时,组件状态集都会重置。

这是应用程序的工作原理。客户端访问他们请求的报价列表 (QuotesRequestedListScreen)。该列表是从 Firebase 加载的,因此指示加载活动的状态首先设置为 true。加载完成后,应用程序会在卡片中显示所有数据。客户端点击卡片后,画面切换,显示卡片信息。但是,如果客户端返回到上一个屏幕,屏幕将永远显示加载活动图标,直到再次切换屏幕。

我曾尝试使用State Persistance given by React Navigation,但当我尝试返回报价列表屏幕 (QuotesRequestedListScreen) 时它不起作用。

有人知道在更改屏幕时保持状态的最佳方法是什么吗?谢谢!

报价主屏幕

const QuoteScreen = (props) => {
  
  const QuotesRequestedScreen = () => {
    return (
      <Stack.Navigator headerMode="none" initialRouteName="Quote List">
        <Stack.Screen name="Quote List" component={QuotesRequestedListScreen} />
        <Stack.Screen name="Card" component={QuoteRequestedCardScreen} />
      </Stack.Navigator>
    );
  };

  return (
    <Tab.Navigator initialRouteName="Request Quote">
      <Tab.Screen name="Request Quote" component={RequestQuoteScreen} />
      <Tab.Screen name="Quotes Requested" component={QuotesRequestedScreen} />
    </Tab.Navigator>
  );
};

export default QuoteScreen;

QuotesRequestedListScreen

const QuotesRequestedListScreen = (props) => {
  //Getting userID for the useEffect
  let userId = useSelector((state) => state.user.userId);
  const {height} = Dimensions.get('window');

  //
  ////USESTATES
  //

  const [quoteStatusCards, setQuoteStatusCards] = useState([]);
  const [airportList, setAirportList] = useState([]);
  const [rawQuotes, setRawQuotes] = useState([]);
  const [errorDetector, setErrorDetector] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [isUserLogged, setIsUserLogged] = useState(true);

  //
  ////USEEFFECTS
  //

  useEffect(() => {
    //Function that starts the verification once it has the focus
    const unsubscribe = props.navigation.addListener('focus', () => {

    if (userId !== null) {
        console.log('Entrei aqui');
        getQuotes();
    } else {
        setIsLoading(false);
        setIsUserLogged(false);
    }
    });

    return unsubscribe;
  }, [userId]);

  //
  //// FUNCTIONS
  //

  const getQuotes = async () => {
    await firebase.getQuotesById(userId).then(async (results) => {
      if (results.isError) {
        errorOperationQuote(results.errorMessage);
      } else {
        //Then it tries to get the airportlist from asyncStorage.
        await AsyncStorage.getItem('airportList')
          .then(async (list) => {
            //Checks if the list is empty
            if (list != null) {
              //If it's not, then it checks the last version in the database with the one stored in the asyncstorage
              await firebase.compareAirportListVersion().then((result) => {
                if (result.isError) {
                  //If there are errors, then it reports the error to the user
                  errorOperationQuote(result.errorMessage);
                } else {
                  if (result.success) {
                    //If it's the same version, then it loads inside airportList;
                    setAirportList(JSON.parse(list));
                    setRawQuotes(results.quotes);
                    setIsLoading(false);
                  } else {
                    //If it's not the same version, then it downloads the whole list again.
                    downloadAirportList(results.quotes);
                  }
                }
              });
            } else {
              //If the list's empty, then it downloads the airport
              downloadAirportList(results.quotes);
            }
          })
          .catch((error) => {
            errorOperationQuote(error.errorMessage);
          });
      }
    });
  };

  //Downloads the airport list and set it to the AirportList state.
  const downloadAirportList = async (quotes) => {
    await firebase.getAirports().then((result) => {
      if (result.success) {
        setAirportList(JSON.parse(result.airportList));
        setRawQuotes(quotes);
      } else {
        errorOperationQuote(result.errorMessage);
      }
    });
  };

  //
  ////RETURN
  //

  return (
    <Container>
      <Content contentContainerStyle={styles.quoteCardsContainer}>
        {isLoading ? (
          <View style={styles.loadingErrorContainers}>
            <Spinner style={{alignItems: 'center'}} color={colors.colorRed} />
          </View>
        ) : !isUserLogged ? (
          <View style={styles.loadingErrorContainers}>
            <Text style={styles.errorMessageText}>
              User is not logged in. Please, log in first before checking the
              quotes requested.
            </Text>
            <Button
              onPress={() => {
                props.navigation.navigate('Login');
              }}>
              Login
            </Button>
          </View>
        ) 
///...
      </Content>
    </Container>
  );

}

QuoteRequestedCardScreen

const QuoteRequestedCardScreen = (props) => {
  const [quoteInfo, setQuoteInfo] = useState(props.route.params?.selectedQuote);
  console.log(quoteInfo);

  return (
    <Container>
      <Content style={{marginHorizontal: 10}}>
        <Card>
          <CardItem style={{paddingLeft: 0}} header>
            <View style={{flexDirection: 'row'}}>
              <Button
                onPress={() => props.navigation.navigate('Quote List')}
                transparent>
                <Icon name="arrow-left" type="FontAwesome5" />
              </Button>
              //...
            </View>
          </CardItem>
        </Card>
      </Content>
    </Container>
  );
};

export default QuoteRequestedCardScreen;

【问题讨论】:

  • 你有没有想过使用 redux 来持久化你的状态?
  • 我有这个想法。我只是不知道哪一个是最好的方法。我会试一试。谢谢!

标签: javascript reactjs react-native react-navigation


【解决方案1】:

问题是您正在另一个组件中创建一个组件。您的函数组件 QuotesRequestedScreenQuoteScreen 函数中定义。

您应该从不在其他组件中定义组件,否则您的状态将在重新渲染时由于重新挂载而丢失。只需将QuotesRequestedScreen 移到QuoteScreen 函数之外,它就会按预期工作。

更多信息来自 React Navigation 文档https://reactnavigation.org/docs/troubleshooting#screens-are-unmountingremounting-during-navigation

【讨论】:

  • 我应该关注一下 React 是如何工作的。这解决了我的问题。非常感谢!
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多