我有一个React Native应用, 在这里,我使用mobx(“ mobx-react”:“ ^ 6.1.8”)并做出反应。
我得到错误: 无效的挂接调用。挂钩只能在功能组件的主体内部调用
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, { 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函数时,出现此错误。
问题是我在helper.js中调用useStores
因此,当我将商店从屏幕传递给助手时,它正在工作。
export const loadAsyncProfileDependencies = async ({
ExamsStore,
UserStore,
CTAStore,
AnswersStore
}) => {
const userID = UserStore.userID;
if (userID) {
UserStore.initUser().then(user => {
UserStore.user = user;
});
CTAStore.getAllCTAS(userID).then(ctas => {
console.log("test", ctas);
CTAStore.ctas = ctas;
});
AnswersStore.getAllAnswers(userID).then(answers => {
AnswersStore.answers = answers.items;
ExamsStore.initExams(answers.items);
});
}
};
有更好的方法吗?而不是通过商店。 这样我就可以在函数中使用此功能?
答案 0 :(得分:0)
如错误所示,您只能在功能组件的根内部使用钩子,而useLoadAsyncProfileDependencies
从技术上讲是自定义钩子,因此您不能在类组件中使用它。
https://reactjs.org/warnings/invalid-hook-call-warning.html
编辑:如前所述,在显示了app.js的代码之后,钩子调用只能在函数组件或自定义钩子的根目录上进行。您需要重新连接代码以使用自定义钩子。
请参阅:https://reactjs.org/docs/hooks-rules.html
您应该返回_handleAppStateChange
的值,以使useEffect
的值作为根组件中依赖的值将按预期正常工作,只有在值更改后才能运行。您还需要将其重写为自定义钩子,以便可以在内部调用钩子。
doTasksEveryTimeWhenAppWillOpenFromBackgorund
和doTasksEveryTimeWhenAppGoesToBackgorund
也应写为自定义钩子,以便您可以在内部调用useLoadAsyncProfileDependencies
。
以一种实用的方式编写这些钩子,以便在不违反钩子规则的情况下,根据需要隔离特定任务和链式钩子。像这样的东西:
const useGetMyData = (params) => {
const [data, setData] = useState()
useEffect(() => {
(async () => {
const apiData = await myApiCall(params)
setData(apiData)
})()
}, [params])
return data
}
然后,您可以根据需要调用该自定义钩子,而不会受到侵犯,例如:
const useShouldGetData = (should, params) => {
if (should) {
return useGetMyData()
}
return null
}
const myApp = () => {
const myData = useShouldGetData(true, {id: 1})
return (
<div>
{JSON.stringify(myData)}
</div>
)
}