我有一个React Native App,在这里,我使用mobx(“ mobx-react”:“ ^ 6.1.8”)并作出反应。
我收到错误:无效的挂接调用。只能在函数组件的主体内部调用挂钩]
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());
import { useContext } from "react";
import UserStore from "./UserStore";
import SettingsStore from "./SettingsStore";
const useStore = () => {
return {
UserStore: useContext(UserStore),
SettingsStore: useContext(SettingsStore),
};
};
export default useStore;
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]);
};
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>
);
});
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的主体内部调用。
正如错误所言,您只能在功能组件的根内部使用钩子,而useLoadAsyncProfileDependencies
从技术上讲是自定义钩子,因此您不能在类组件中使用它。