繁体   English   中英

React Native:更换屏幕时如何防止 state 重置?

[英]React Native: How to prevent state reset when changing screens?

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

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

我尝试使用由 React Navigation 提供的 State 持久性,但是当我尝试返回报价列表屏幕(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;

报价请求列表屏幕

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>
  );

}

报价请求卡屏幕

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;

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

永远不应该在其他组件中定义组件,否则您的 state 将由于重新安装而在重新渲染时丢失。 只需将QuotesRequestedScreen移到QuoteScreen function 之外,它就会按预期工作。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM