在渲染组件之前 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 屏幕; 包含TabNavigatorMainFlow 屏幕。

TabNavigator 有两个屏幕,FeedScreenAccountMore,其中初始屏幕是 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;

getAllQuestionsQuestionContext 中的一个函数,它进行 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 仍然尝试访问状态

ScrollView 在 react-native 中渲染没有数据的更新组件?

在 React Native 中更新渲染组件

为啥组件在状态更改后不重新渲染。在 react-native 函数组件中