[英]React Hooks + Mobx => Invalid hook call. Hooks can only be called inside of the body of a function component
I have a React Native App, Here i use mobx ("mobx-react": "^6.1.8") and react hooks.我有一个 React Native 应用程序,在这里我使用 mobx ("mobx-react": "^6.1.8") 和 react hooks。
i get the error: Invalid hook call.我收到错误:无效的钩子调用。 Hooks can only be called inside of the body of a function component
Hooks 只能在函数组件内部调用
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>
);
});
so now, when i call the useLoadAsyncProfileDependencies function, i get this error.所以现在,当我调用 useLoadAsyncProfileDependencies 函数时,我收到此错误。
The Problem is that i call useStores in helper.js问题是我在 helper.js 中调用 useStores
so when i pass the Stores from the Screen to the helper it is working.所以当我将 Stores 从屏幕传递给助手时,它正在工作。
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);
});
}
};
Is there a better way?有没有更好的办法? instead passing the Stores.
而是通过商店。 So that i can use this function in functions?
这样我就可以在函数中使用这个函数了?
As the error says, you can only use hooks inside the root of a functional component, and your useLoadAsyncProfileDependencies
is technically a custom hook so you cant use it inside a class component.正如错误所说,您只能在功能组件的根内使用钩子,而您的
useLoadAsyncProfileDependencies
从技术useLoadAsyncProfileDependencies
是一个自定义钩子,因此您不能在类组件内使用它。
https://reactjs.org/warnings/invalid-hook-call-warning.html https://reactjs.org/warnings/invalid-hook-call-warning.html
EDIT: Well after showing the code for app.js, as mentioned, hook calls can only be done top level from a function component or the root of a custom hook.编辑:正如前面提到的,在显示 app.js 的代码之后,钩子调用只能在函数组件或自定义钩子的根的顶层完成。 You need to rewire your code to use custom hooks.
您需要重新连接代码以使用自定义挂钩。
SEE THIS: https://reactjs.org/docs/hooks-rules.html看到这个: https : //reactjs.org/docs/hooks-rules.html
You should return the value for _handleAppStateChange
so your useEffect
's the value as a depdendency in your root component would work properly as intended which is should run only if value has changed.您应该返回
_handleAppStateChange
的值,以便您的useEffect
作为根组件中的依赖项的值将按预期正常工作,只有在值更改时才应运行。 You also need to rewrite that as a custom hook so you can call hooks inside.您还需要将其重写为自定义钩子,以便您可以在内部调用钩子。
doTasksEveryTimeWhenAppWillOpenFromBackgorund
and doTasksEveryTimeWhenAppGoesToBackgorund
should also be written as a custom hook so you can call useLoadAsyncProfileDependencies
inside. doTasksEveryTimeWhenAppWillOpenFromBackgorund
和doTasksEveryTimeWhenAppGoesToBackgorund
也应编写为自定义钩子,以便您可以在内部调用useLoadAsyncProfileDependencies
。
write those hooks in a functional way so you are isolating specific tasks and chain hooks as you wish without violiating the rules of hooks.以函数式方式编写这些钩子,这样您就可以在不违反钩子规则的情况下根据需要隔离特定任务和链钩子。 Something like this:
像这样的东西:
const useGetMyData = (params) => {
const [data, setData] = useState()
useEffect(() => {
(async () => {
const apiData = await myApiCall(params)
setData(apiData)
})()
}, [params])
return data
}
Then you can call that custom hook as you wish without violation like:然后您可以根据需要调用该自定义钩子而不会违反,例如:
const useShouldGetData = (should, params) => {
if (should) {
return useGetMyData()
}
return null
}
const myApp = () => {
const myData = useShouldGetData(true, {id: 1})
return (
<div>
{JSON.stringify(myData)}
</div>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.