React Hooks + Mobx =>无效的挂钩调用。只能在函数组件的主体内部调用钩子

问题描述 投票:0回答:1

我有一个React Native App,在这里,我使用mobx(“ mobx-react”:“ ^ 6.1.8”)并作出反应。

我收到错误:无效的挂接调用。只能在函数组件的主体内部调用挂钩]

MOBX USERSTORE
import * as React from "react";
import { observable, action } from "mobx";

class UserStore {
  @observable user = null;

  @action
  async createProfile() {
    const answer = await query("createProfile");
    return answer;
  }

  @action
  async logout() {
    return Auth.signOut({ global: true })
      .then(data => {
        this.userID = null;
      })
      .catch(err => console.log(err));
  }

  }

export default React.createContext(new UserStore());

存储index.js
import { useContext } from "react";
import UserStore from "./UserStore";
import SettingsStore from "./SettingsStore";


const useStore = () => {
  return {
    UserStore: useContext(UserStore),
    SettingsStore: useContext(SettingsStore),
  };
};

export default useStore;

helper.js
    import React from "react";
    import useStores from "../stores";

    export const useLoadAsyncProfileDependencies = userID => {
  const { ExamsStore, UserStore, CTAStore, AnswersStore } = useStores();
  const [user, setUser] = useState({});
  const [ctas, setCtas] = useState([]);
  const [answers, setAnswers] = useState([]);

  useEffect(() => {
    if (userID) {
      (async () => {
        const user = await UserStore.initUser();
        UserStore.user = user;
        setUser(user);
      })();
      (async () => {
        const ctas = await CTAStore.getAllCTAS(userID);
        CTAStore.ctas = ctas;
        setCtas(ctas);
      })();
      (async () => {
        const answers = await AnswersStore.getAllAnswers(userID);
        UserStore.user.answers = answers.items;
        AnswersStore.answers = answers.items;
        ExamsStore.initExams(answers.items);
        setAnswers(answers.items);
      })();
    }
  }, [userID]);
};

Navigator.js
import React from "react";
import { View, Text, Button } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Colors from "../constants/Colors";
import { observer } from "mobx-react";
import useStores from "../stores";
import { useLoadAsyncProfileDependencies } from "../helper/app";

import {
  SignIn,

} from "../screens";
...
const RootStack = createStackNavigator();

export const RootStackScreen = observer(() => {
  const { ExamsStore, UserStore, CTAStore, AnswersStore } = useStores();
  const userID = UserStore.userID;

  useLoadAsyncProfileDependencies();

  return (
    <NavigationContainer>
      <RootStack.Navigator headerMode="none" mode="modal">
        {userID ? (
          <RootStack.Screen
            name="App"
            component={TabsScreen}
            options={{
              animationEnabled: false
            }}
          />
        ) : (
          <RootStack.Screen
            name="Auth"
            component={AuthStackScreen}
            options={{
              animationEnabled: false
            }}
          />
        )}
        <RootStack.Screen name="LevelOverview" component={LevelOverview} />
        {/** PLACE MORE MODALS HERE */}
      </RootStack.Navigator>
    </NavigationContainer>
  );
});

App.js
import * as React from "react";
import { Platform, StatusBar, Alert, AppState } from "react-native";
import { Updates, Notifications } from "expo";
import { SplashScreen } from "expo";
import * as Font from "expo-font";
import { Ionicons } from "@expo/vector-icons";
import moment from "moment";
import "moment/locale/de";
import Constants from "expo-constants";
import Amplify, { Auth } from "aws-amplify";
import { AlertProvider } from "./components/Alert";
import { RootStackScreen } from "./navigation/Navigator";
import useLinking from "./navigation/useLinking";
import Tracking, { updateUserProperties } from "./tracking";
import NetInfo from "@react-native-community/netinfo";
import aws_exports from "./aws-exports";
import AmplifyStoragefix from "./Amplify-Storage-fix";
import { TimeInApp, AppOpens, AppOpensUnique } from "./utilities/kpi";
import useStore from "./stores";
import { useLoadAsyncProfileDependencies } from "./helper/app";
moment.locale("de");


export default props => {
  const [isLoadingComplete, setLoadingComplete] = React.useState(false);
  const [appState, setAppState] = React.useState("");
  const [connectionInfo, setConnectionInfo] = React.useState("");
  const [initialNavigationState, setInitialNavigationState] = React.useState();
  const containerRef = React.useRef();
  const { getInitialState } = useLinking(containerRef);
  const { UserStore, InternetConnectionStore } = useStore();
  let time_in_app = Date.now();
  let _checking_update = false;

  React.useEffect(() => {

    if (Platform.OS !== "web") {
      AppState.addEventListener("change", _appState => setAppState(_appState));
      NetInfo.addEventListener(state => setConnectionInfo(state));
      return () => {
        AppState.addEventListener("change", _appState =>
          setAppState(_appState)
        );
        NetInfo.addEventListener(state => {
          setConnectionInfo(state);
        });
      };
    }
  }, []);

  React.useEffect(() => {
    _handleConnectivityChange();
  }, [connectionInfo]);

  React.useEffect(() => {
   if (!appState.match(/inactive|background/)) {
        await doTasksEveryTimeWhenAppWillOpenFromBackgorund();
      } else {
        await doTasksEveryTimeWhenAppGoesToBackgorund();
      }
  }, [appState]);

  async function getCurrentAuthenticatedUser() {
    return await UserStore.currentAuthenticatedUser();
  }



  async function doTasksEveryTimeWhenAppWillOpenFromBackgorund() {
     _checkUpdates(); //Expo JS Bundle Update check
     time_in_app = Date.now();
     const cognitoUser = await UserStore.currentAuthenticatedUser();
     //When user is authenticated
     if (cognitoUser !== "not authenticated") {
       UserStore.userID = cognitoUser.username;
       await UserStore.updateUser({ online: 1 });
       AppOpens();
       AppOpensUnique();
       useLoadAsyncProfileDependencies(UserStore.userID);
     } else {
       //When user is NOT authenticated
       console.log(cognitoUser);
     }
  }

  async function doTasksEveryTimeWhenAppGoesToBackgorund() {
    const cognitoUser = await UserStore.currentAuthenticatedUser();
    // //When user is authenticated
     if (cognitoUser !== "not authenticated") {
       let timeInMs = Date.now() - this.time_in_app;
       if (timeInMs >= 60000) {
         let timeInMinutes = timeInMs / 60000;
         TimeInApp(Math.round(timeInMinutes));
       }
       await UserStore.updateUser({ last_seen: new Date(), online: 0 });
     }
     if (UserStore.user) {
       //Tracking
       updateUserProperties(UserStore.user);
       Tracking.trackEvent("AppState", { name: "GoForeground" });
     }
  }

  async function _handleConnectivityChange() {
    if (connectionInfo.type == "none") {
      InternetConnectionStore.isOffline = true;
    }
  }

  async function loadResourcesAndDataAsync() {
    try {
      SplashScreen.preventAutoHide();
      setInitialNavigationState(await getInitialState());
      console.log("initNavState", await getInitialState());
      await Font.loadAsync({
        ...Ionicons.font,
        Light: require("./assets/fonts/FiraSans-Light.ttf"),
        SemiBold: require("./assets/fonts/FiraSans-SemiBold.ttf"),
        Medium: require("./assets/fonts/FiraSans-Medium.ttf"),
        Regular: require("./assets/fonts/FiraSans-Regular.ttf")
      });
    } catch (e) {
      console.warn(e);
    } finally {
      setLoadingComplete(true);
      SplashScreen.hide();
    }
  }

  if (!isLoadingComplete && !props.skipLoadingScreen) {
    return null;
  } else {
    return (
      <AlertProvider>
        <RootStackScreen />
      </AlertProvider>
    );
  }
};


export const AppOpens = async () => {
  const { UserStore } = useStore();
  const { opens_app } = UserStore.user;
  if (opens_app === null) {
    const res = await UserStore.updateUser({ opens_app: 2 });
  } else {
    const res = await UserStore.updateUser({ opens_app: opens_app + 1 });
  }
};

屏幕
import React, { useEffect, useState, useRef } from "react";
import {
  View,
  Dimensions,
  SafeAreaView,
  ScrollView,
  StyleSheet
} from "react-native";
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp
} from "react-native-responsive-screen";

import { observer } from "mobx-react";
import useStores from "../../stores";
import { useLoadAsyncProfileDependencies } from "../../helper/app";
const windowWidth = Dimensions.get("window").width;

export default observer(({ navigation }) => {
  const {
    UserStore,
    ExamsStore,
    CTAStore,
    InternetConnectionStore
  } = useStores();
  const scrollViewRef = useRef();

  const [currentSlide, setCurrentSlide] = useState(0);

  useEffect(() => {
    if (InternetConnectionStore.isOffline) {
      return;
    }
    Tracking.trackEvent("opensScreen", { name: "Challenges" });
    useLoadAsyncProfileDependencies(UserStore.userID);
  }, []);

  React.useEffect(() => {
    const unsubscribe = navigation.addListener("focus", () => {
      CTAStore.popBadget(BadgetNames.ChallengesTab);
    });
    return unsubscribe;
  }, [navigation]);

  async function refresh() {
    const user = await UserStore.initUser(); //wird das gebarucht?
    useLoadAsyncProfileDependencies(UserStore.userID);
    if (user) {
      InternetConnectionStore.isOffline = false;
    }
  }

  const name = UserStore.name;

  return (
    <SafeAreaView style={styles.container} forceInset={{ top: "always" }}>

    </SafeAreaView>
  );
});

所以现在,当我调用useLoadAsyncProfileDependencies函数时,出现此错误。目前,我从Navigator.js和App.js中调用它

任何想法?

我有一个React Native App,在这里我使用mobx(“ mobx-react”:“ ^ 6.1.8”)和react钩子。我收到错误:无效的挂接调用。挂钩只能在功能组件MOBX的主体内部调用。

reactjs react-hooks mobx
1个回答
0
投票

正如错误所言,您只能在功能组件的根内部使用钩子,而useLoadAsyncProfileDependencies从技术上讲是自定义钩子,因此您不能在类组件中使用它。

© www.soinside.com 2019 - 2024. All rights reserved.