在渲染组件之前 React Native fetch
Posted
技术标签:
【中文标题】在渲染组件之前 React Native fetch【英文标题】:React Native fetch before render components 【发布时间】:2020-09-13 02:10:32 【问题描述】:我正在创建一个 Reat Native 应用程序,该应用程序连接到它从中获取数据的 API。
我正在使用 React Navigation 来处理导航。该应用程序有一个堆栈导航器和一个底部选项卡导航器。 StackNavigator
有 4 个屏幕:
SignupScreen
负责创建帐户;
LoginScreen
用于手动登录;
SplashScreen
检查本地令牌并自动登录用户;
LoadingScreen
触发对 API 的初始 fetch 调用,将响应存储在 state 中并导航到 MainFlow
屏幕;
包含TabNavigator
的MainFlow
屏幕。
TabNavigator
有两个屏幕,FeedScreen
、Account
和 More
,其中初始屏幕是 FeedScreen
。
注册/登录/本地流程都运行良好。
问题:一旦用户成功登录,LoadingScreen 就会触发 API 调用,但 MainFlow
组件会在数据处于状态之前呈现。因为MainFlow
中的组件需要数据,所以会报错。如何仅在数据存在后才呈现 FeedScreen
组件?
在LoadingScreen
中,我正在从上下文对象QuestionContext
触发对useEffect
的API 调用:
const LoadingScreen = ( navigation ) =>
const [loading, setLoading] = useState(true);
const state: authState = useContext(AuthContext);
const getQuestionsForUser, getAllQuestions = useContext(QuestionContext);
useEffect(() =>
getAllQuestions();
, []);
return (
<View style=styles.container>
<YonStatusBar backgroundColor="#310B3B" />
<Image source=splashLogo containerStyle=styles.splashLogo />
<ActivityIndicator />
</View>
);
;
export default LoadingScreen;
getAllQuestions
是 QuestionContext
中的一个函数,它进行 API 调用并导航到 FeedScreen
:
const getAllQuestions = (dispatch) =>
return async () =>
try
const token = await AsyncStorage.getItem('token');
const config = headers: Authorization: `Bearer $token` ;
const response = await yonyonApi.get(`/questions`, config);
dispatch( type: 'GET_ALL_QUESTIONS', payload: response.data );
RootNavigation.navigate('MainFlow');
catch (e)
console.log(e);
;
;
getAllQuestions
工作正常:API 调用成功,我可以看到响应存储在 state 中。但是,它会在此之前导航到 MainFlow
。
最后,这是FeedScreen
:
const FeedScreen = () =>
const state: questionState = useContext(QuestionContext);
return (
<ScrollView style=styles.container>
console.log(questionState.questions)
<View style=styles.listContainer>
<QuestionCard />
</View>
</ScrollView>
);
;
export default FeedScreen;
FeedScreen
呈现一个QuestionCard
,它需要questionState
中的数据。这就是引发错误的原因:QuestionCard
在数据处于状态之前被渲染。
一旦必要的数据处于状态,我怎样才能让导航只导航到FeedScreen
?或者,在数据不存在时渲染QuestionCard
以外的其他内容,一旦数据在questionState
中,渲染QuestionCard
?
【问题讨论】:
【参考方案1】:为什么不将上下文的初始状态设置为null
,如果不是null
,则渲染组件?
const [questionState, setQuestionState] = useState(null);
...
const FeedScreen = () =>
const state: questionState = useContext(QuestionContext);
return (
<ScrollView style=styles.container>
!!questionState?.questions && console.log(questionState.questions)
<View style=styles.listContainer>
<QuestionCard />
</View>
</ScrollView>
);
;
export default FeedScreen;
【讨论】:
【参考方案2】:对我来说,我将使用屏幕而不是两个屏幕,如下所示:
const FeedScreen = () =>
const [loading, setLoading] = useState(true);
const state: authState = useContext(AuthContext);
const [data, setData] = useState([]);
const getAllQuestions = (dispatch) =>
return async () =>
try
const token = await AsyncStorage.getItem('token');
const config = headers: Authorization: `Bearer $token` ;
const response = await yonyonApi.get(`/questions`, config);
setData(response.data)
setLoading(false)
catch (e)
console.log(e);
;
;
useEffect(() =>
getAllQuestions();
, []);
return (
<ScrollView style=styles.container>
(loading)?
<ActivityIndicator/>
:
<View style=styles.listContainer>
<QuestionCard data=data/>
</View>
</ScrollView>
);
;
export default FeedScreen;
【讨论】:
感谢您的支持。帮助。但是,这不允许我使用存储在上下文中的状态变量。我不想在我的屏幕中创建本地状态,而是使用上下文中的一个。目前,上下文负责所有异步操作,例如进行 API 调用。在渲染 QuestionCard 组件之前,如何在屏幕上等待所有这些操作完成并填充状态?谢谢以上是关于在渲染组件之前 React Native fetch的主要内容,如果未能解决你的问题,请参考以下文章
React Native this.setState() 仅在再次与组件交互后重新渲染
「React Native」子组件Render中props为空报错问题
即使设置为 false,使用条件渲染的 React Native 仍然尝试访问状态