在渲染组件之前反应本机提取

时间:2020-05-26 09:52:43

标签: reactjs react-native react-navigation render use-effect

我正在创建一个Reat Native应用程序,该应用程序连接到API并从中获取数据。

我正在使用React Navigation来处理导航。该应用程序具有堆栈导航器和底部选项卡导航器。 StackNavigator有4个屏幕:

  • SignupScreen,负责创建帐户;
  • LoginScreen进行手工登录;
  • SplashScreen,用于检查本地令牌并自动登录用户;
  • 一个LoadingScreen,它会触发对API的初始提取调用,将响应存储在状态中,并导航到MainFlow屏幕;
  • 一个MainFlow屏幕,其中包含TabNavigator

TabNavigator有两个屏幕,FeedScreenAccountMore,其中初始屏幕为FeedScreen

注册/登录/本地流均正常运行。

问题:用户成功登录后,LoadingScreen会触发API调用,但是在数据处于状态之前会呈现MainFlow组件。由于MainFlow中的组件需要数据,因此会引发错误。仅在数据存在后,才如何渲染FeedScreen组件?

LoadingScreen中,我从上下文对象useEffect触发了QuestionContext的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调用成功,并且可以看到响应存储在状态中。但是,它会在发生这种情况之前导航到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

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

为什么不将上下文的初始状态设置为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;