[英]Warning: Can't perform a React state update on an unmounted component. How to use did mount
My code has a problem at the time of login, when I change the screens and the auth is done.我的代码在登录时出现问题,当我更改屏幕并完成身份验证时。 I don't know what the solution is but I think that by mistake it was the did mount that I don't know how to use: DI looked for the did mount but I don't know how to use it even more, I have to find out how it works
我不知道解决方案是什么,但我认为错误地是我不知道如何使用的安装:DI 寻找了安装,但我不知道如何使用它,我必须找出它是如何工作的
ERROR Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in Home (at SceneView.tsx:122)
(...)
in StackNavigator (at MainStack.routes.js:11)
in HomeStack (at App.js:32)
import React, { useState, useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import MainStack from "./Routes/MainStack.routes";
import HomeStack from "./Routes/HomeStack.routes";
import auth from "@react-native-firebase/auth";
import Load from "./Components/Load";
import AsyncStorage from "@react-native-async-storage/async-storage";
export default function App() {
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState();
async function onAuthStateChanged(userLoged) {
setUser(userLoged);
if (userLoged) {
await AsyncStorage.setItem("lolguide@user", JSON.stringify(userLoged));
}
if (initializing) setInitializing(false);
}
useEffect(() => {
return auth().onAuthStateChanged(onAuthStateChanged);
}, []);
if (initializing) {
return <Load />;
}
if (!user) {
return (
<NavigationContainer>
<MainStack />
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<HomeStack />
</NavigationContainer>
);
}
}
import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import Load from "../Components/Load";
import MainStackScreen from "../Routes/MainStack.routes";
import Home from "../Pages/Home/index";
import Profile from "../Pages/Profile";
import Champ from "../Pages/Champ/index";
const MainStack = createStackNavigator();
const HomeStackScreens = () => (
<MainStack.Navigator headerMode="none">
<MainStack.Screen name="HomeScreen" component={Home} />
<MainStack.Screen name="Loading" component={Load} />
<MainStack.Screen
name="LoginHome"
component={MainStackScreen}
/>
<MainStack.Screen name="Profile" component={Profile}/>
<MainStack.Screen name="Champ" component={Champ}/>
</MainStack.Navigator>
);
export default HomeStackScreens;
import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import Login from "../Pages/Login/index";
import SignUp from "../Pages/SignUp/index";
import Load from "../Components/Load";
import Home from "../Routes/HomeStack.routes";
const MainStack = createStackNavigator();
const HomeStack = () => (
<MainStack.Navigator headerMode="none">
<MainStack.Screen name="Login" component={Login} />
<MainStack.Screen name="SignUp" component={SignUp} />
<MainStack.Screen name="Loading" component={Load} />
<MainStack.Screen name="HomeScreen" component={Home} />
</MainStack.Navigator>
);
export default HomeStack;
import React, { useState, useEffect } from "react";
import { Container } from "./styles";
import Header from "../../Components/Header";
import Load from "../../Components/Load";
import ChampCard from "../../Components/ChampCard";
import { FlatList, StatusBar, TouchableOpacity } from "react-native";
import { useNavigation } from '@react-navigation/native';
const Home = () => {
const [loading, setLoading] = useState(true);
const [champs, setChamps] = useState([]);
const navigation = useNavigation();
function navegar(tela, props) {
navigation.navigate(tela, {item: JSON.stringify(props)});
}
async function getData() {
await fetch(
"https://ddragon.leagueoflegends.com/cdn/11.10.1/data/pt_BR/champion.json"
)
.then((res) => res.json())
.then((json) => setChamps(Object.values(json.data)));
setLoading(false);
}
useEffect(() => {
getData();
}, []);
if (loading) {
return <Load />;
}
return (
<>
<Container>
<Header type="NormalHeader"/>
{champs.length > 0 ? (
<FlatList
data={champs}
keyExtractor={(item) => item.key}
renderItem={(item) => (
<TouchableOpacity onPress={() => navegar("Champ", item)}>
<ChampCard item={item}/>
</TouchableOpacity>
)}
contentContainerStyle={{ paddingBottom: 65 }}
showsVerticalScrollIndicator={false}
/>
) : (
<Load />
)}
</Container>
<StatusBar backgroundColor="#000"/>
</>
);
};
export default Home;
import React, { useState } from "react";
import { Image, Dimensions, PixelRatio, StyleSheet } from "react-native";
import { StatusBar } from "expo-status-bar";
import { LinearGradient } from "expo-linear-gradient";
import { useNavigation } from "@react-navigation/native";
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
Container,
Logo,
TextInput,
Text,
Button,
ButtonArea,
ImageBox,
ViewAbsolute,
} from "./styles";
import Load from "../../Components/Load";
import auth from "@react-native-firebase/auth";
const widthPercentageToDP = (widthPercent) => {
const screenWidth = Dimensions.get("window").width;
return PixelRatio.roundToNearestPixel(
(screenWidth * parseFloat(widthPercent)) / 100
);
};
const heightPercentageToDP = (heightPercent) => {
const screenHeight = Dimensions.get("window").height;
return PixelRatio.roundToNearestPixel(
(screenHeight * parseFloat(heightPercent)) / 100
);
};
const styles = StyleSheet.create({
linearGradient: {
height: heightPercentageToDP("120%"),
flex: 1,
},
});
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const navigation = useNavigation();
const handleSend = () => {
if (email && password) {
setIsLoading(true);
auth()
.signInWithEmailAndPassword(email, password)
.then( () => {
navigation.navigate("HomeScreen");
setIsLoading(false);
})
.catch((error) => {
if (error.code) {
console.error(error);
}
});
setIsLoading(false);
} else {
alert("Preencha os campos!");
}
};
const handleRegisterNavigate = () => {
navigation.navigate("SignUp");
};
if (isLoading) {
return <Load />;
}
return (
<ViewAbsolute>
<Container>
<LinearGradient
colors={["#C28F2C", "#000", "#004840"]}
style={styles.linearGradient}
start={{ x: 0, y: -0.2 }}
end={{ x: 0, y: 1.2 }}
>
<Logo>
<Image
source={require("../../Assets/lolGuideIcon.png")}
style={{ height: 75, width: 80 }}
resizeMode="stretch"
/>
</Logo>
<Text>O primeiro passo para se tornar um campeão é a iniciativa</Text>
<TextInput
placeholder="Email"
keyboardType="email-address"
margin_top="50px"
value={email}
onChangeText={(t) => setEmail(t)}
/>
<TextInput
placeholder="Senha"
margin_top="5px"
secureTextEntry
value={password}
onChangeText={(t) => setPassword(t)}
/>
<ButtonArea>
<Button width="80px" margin_top="20px" onPress={handleSend}>
<Text>Entrar</Text>
</Button>
<Button
width="110px"
margin_top="10px"
onPress={handleRegisterNavigate}
>
<Text>Registrar</Text>
</Button>
</ButtonArea>
<ImageBox>
<Image
source={require("../../Assets/Pyke-transparente.png")}
style={{
height: 230,
width: 260,
}}
/>
</ImageBox>
<StatusBar style="auto" backgroundColor="transparent" />
</LinearGradient>
</Container>
</ViewAbsolute>
);
};
export default Login;
I FOUND IT:!!我找到了:!! The problem was because I was navigating to other screen while my useEffect was working so: I remove the navigate in Login and SignUp screen and that works
问题是因为我在 useEffect 工作时导航到其他屏幕,所以:我删除了登录和注册屏幕中的导航,并且有效
import React, { useState } from "react";
import { Image, Dimensions, PixelRatio, StyleSheet } from "react-native";
import { StatusBar } from "expo-status-bar";
import { LinearGradient } from "expo-linear-gradient";
import { useNavigation } from "@react-navigation/native";
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
Container,
Logo,
TextInput,
Text,
Button,
ButtonArea,
ImageBox,
ViewAbsolute,
} from "./styles";
import Load from "../../Components/Load";
import auth from "@react-native-firebase/auth";
const widthPercentageToDP = (widthPercent) => {
const screenWidth = Dimensions.get("window").width;
return PixelRatio.roundToNearestPixel(
(screenWidth * parseFloat(widthPercent)) / 100
);
};
const heightPercentageToDP = (heightPercent) => {
const screenHeight = Dimensions.get("window").height;
return PixelRatio.roundToNearestPixel(
(screenHeight * parseFloat(heightPercent)) / 100
);
};
const styles = StyleSheet.create({
linearGradient: {
height: heightPercentageToDP("120%"),
flex: 1,
},
});
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const navigation = useNavigation();
const handleSend = () => {
if (email && password) {
setIsLoading(true);
auth()
.signInWithEmailAndPassword(email, password)
//.then( () => {
// navigation.navigate("HomeScreen"); REMOVE THIS BLOCK
// setIsLoading(false);
//})
.catch((error) => {
if (error.code) {
console.error(error);
}
});
setIsLoading(false);
} else {
alert("Preencha os campos!");
}
};
const handleRegisterNavigate = () => {
navigation.navigate("SignUp");
};
if (isLoading) {
return <Load />;
}
return (
<ViewAbsolute>
<Container>
<LinearGradient
colors={["#C28F2C", "#000", "#004840"]}
style={styles.linearGradient}
start={{ x: 0, y: -0.2 }}
end={{ x: 0, y: 1.2 }}
>
<Logo>
<Image
source={require("../../Assets/lolGuideIcon.png")}
style={{ height: 75, width: 80 }}
resizeMode="stretch"
/>
</Logo>
<Text>O primeiro passo para se tornar um campeão é a iniciativa</Text>
<TextInput
placeholder="Email"
keyboardType="email-address"
margin_top="50px"
value={email}
onChangeText={(t) => setEmail(t)}
/>
<TextInput
placeholder="Senha"
margin_top="5px"
secureTextEntry
value={password}
onChangeText={(t) => setPassword(t)}
/>
<ButtonArea>
<Button width="80px" margin_top="20px" onPress={handleSend}>
<Text>Entrar</Text>
</Button>
<Button
width="110px"
margin_top="10px"
onPress={handleRegisterNavigate}
>
<Text>Registrar</Text>
</Button>
</ButtonArea>
<ImageBox>
<Image
source={require("../../Assets/Pyke-transparente.png")}
style={{
height: 230,
width: 260,
}}
/>
</ImageBox>
<StatusBar style="auto" backgroundColor="transparent" />
</LinearGradient>
</Container>
</ViewAbsolute>
);
};
export default Login;
The onAuthStateChanged
function makes the dependencies of useEffect()
Hook change on every render. onAuthStateChanged
function 使useEffect()
Hook 的依赖关系在每次渲染时都发生变化。 Move it inside the useEffect
callback.将它
useEffect
回调中。 Alternatively, you can wrap the definition of onAuthStateChanged
in its own useCallback()
Hook.或者,您可以将
onAuthStateChanged
的定义包装在它自己的useCallback()
Hook 中。
The updated code for App.js
:- App.js
的更新代码:-
import React, { useState, useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import MainStack from "./Routes/MainStack.routes";
import HomeStack from "./Routes/HomeStack.routes";
import auth from "@react-native-firebase/auth";
import Load from "./Components/Load";
import AsyncStorage from "@react-native-async-storage/async-storage";
export default function App() {
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState();
useEffect(() => {
auth().onAuthStateChanged((userLogged) => {
setUser(userLogged);
if (userLogged) {
AsyncStorage.setItem("lolguide@user", JSON.stringify(userLogged));
}
if (initializing) setInitializing(false);
});
}, [initializing]);
if (initializing) {
return <Load />;
}
if (!user) {
return (
<NavigationContainer>
<MainStack />
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<HomeStack />
</NavigationContainer>
);
}
}
Memory leak usually when be will happened, you in the asynchronous function after that your component was unmounted, update your states. Memory 泄漏通常什么时候会发生,你在异步 function 之后你的组件被卸载,更新你的状态。 you are able to handle it by useRef (as one of the solutions), So try followings this, i hope this help you:
您可以通过useRef处理它(作为解决方案之一),因此请尝试以下操作,希望对您有所帮助:
Home家
import React, { useState, useEffect } from "react";
import { Container } from "./styles";
import Header from "../../Components/Header";
import Load from "../../Components/Load";
import ChampCard from "../../Components/ChampCard";
import { FlatList, StatusBar, TouchableOpacity } from "react-native";
import { useNavigation } from '@react-navigation/native';
const Home = () => {
const isMounted = React.useRef(null);
const [loading, setLoading] = useState(true);
const [champs, setChamps] = useState([]);
const navigation = useNavigation();
function navegar(tela, props) {
navigation.navigate(tela, {item: JSON.stringify(props)});
}
async function getData() {
await fetch(
"https://ddragon.leagueoflegends.com/cdn/11.10.1/data/pt_BR/champion.json"
)
.then((res) => res.json())
.then((json) => {
if (isMounted.current)
setChamps(Object.values(json.data)));
}
setLoading(false);
}
useEffect(() => {
isMounted.current = true;
getData();
return ()=> {
isMounted.current = false;
};
}, []);
if (loading) {
return <Load />;
}
return (
<>
<Container>
<Header type="NormalHeader"/>
{champs.length > 0 ? (
<FlatList
data={champs}
keyExtractor={(item) => item.key}
renderItem={(item) => (
<TouchableOpacity onPress={() => navegar("Champ", item)}>
<ChampCard item={item}/>
</TouchableOpacity>
)}
contentContainerStyle={{ paddingBottom: 65 }}
showsVerticalScrollIndicator={false}
/>
) : (
<Load />
)}
</Container>
<StatusBar backgroundColor="#000"/>
</>
);
};
export default Home;
Also if you see this warning whenever, you can use the approach for handle that.此外,如果您随时看到此警告,则可以使用该方法进行处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.