admin管理员组文章数量:1387457
I am having trouble when changing screens after the user access a card. The ponent set of states resets whenever the client accesses a card, changes the screen, and returns to the same ponent before.
Here is how the app works. The client access a list of quotes (QuotesRequestedListScreen) that they requested. This said list is loaded from Firebase, and thus the state to indicate loading activity is set to true at first. After the load finishes, then the app shows all the data in cards. After the client clicks on the card, it changes the screen and displays the card info. However, if the client returns to the previous screen, the screen shows the loading activity icon forever until changing screens again.
I have tried to use State Persistance given by React Navigation, but it did not work when I was trying to return to the quote list screen (QuotesRequestedListScreen).
Does someone know what is the best way to keep the states when changing screens? Thanks!
Main Quote Screen
const QuoteScreen = (props) => {
const QuotesRequestedScreen = () => {
return (
<Stack.Navigator headerMode="none" initialRouteName="Quote List">
<Stack.Screen name="Quote List" ponent={QuotesRequestedListScreen} />
<Stack.Screen name="Card" ponent={QuoteRequestedCardScreen} />
</Stack.Navigator>
);
};
return (
<Tab.Navigator initialRouteName="Request Quote">
<Tab.Screen name="Request Quote" ponent={RequestQuoteScreen} />
<Tab.Screen name="Quotes Requested" ponent={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 firebasepareAirportListVersion().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;
I am having trouble when changing screens after the user access a card. The ponent set of states resets whenever the client accesses a card, changes the screen, and returns to the same ponent before.
Here is how the app works. The client access a list of quotes (QuotesRequestedListScreen) that they requested. This said list is loaded from Firebase, and thus the state to indicate loading activity is set to true at first. After the load finishes, then the app shows all the data in cards. After the client clicks on the card, it changes the screen and displays the card info. However, if the client returns to the previous screen, the screen shows the loading activity icon forever until changing screens again.
I have tried to use State Persistance given by React Navigation, but it did not work when I was trying to return to the quote list screen (QuotesRequestedListScreen).
Does someone know what is the best way to keep the states when changing screens? Thanks!
Main Quote Screen
const QuoteScreen = (props) => {
const QuotesRequestedScreen = () => {
return (
<Stack.Navigator headerMode="none" initialRouteName="Quote List">
<Stack.Screen name="Quote List" ponent={QuotesRequestedListScreen} />
<Stack.Screen name="Card" ponent={QuoteRequestedCardScreen} />
</Stack.Navigator>
);
};
return (
<Tab.Navigator initialRouteName="Request Quote">
<Tab.Screen name="Request Quote" ponent={RequestQuoteScreen} />
<Tab.Screen name="Quotes Requested" ponent={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.pareAirportListVersion().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;
Share
Improve this question
asked Jul 22, 2020 at 21:42
LeminurLeminur
3613 gold badges10 silver badges24 bronze badges
2
- 4 Have you though about using redux to persist your state? – osekmedia Commented Jul 22, 2020 at 21:46
- I had that in mind. I just did not figure out which one was the best way out of this. I shall give it a try. Thanks! – Leminur Commented Jul 23, 2020 at 0:43
1 Answer
Reset to default 6The problem is that you're creating a ponent inside another ponent. Your function ponent QuotesRequestedScreen
is defined inside the QuoteScreen
function.
You should NEVER define ponents inside other ponents or your state will be lost on re-render due to remount. Just move the QuotesRequestedScreen
to outside the QuoteScreen
function and then it'll work as expected.
More information from React Navigation docs https://reactnavigation/docs/troubleshooting#screens-are-unmountingremounting-during-navigation
本文标签: javascriptReact Native How to prevent state reset when changing screensStack Overflow
版权声明:本文标题:javascript - React Native: How to prevent state reset when changing screens? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744512173a2609947.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论