我的代码在登录时出现问题,当我更改屏幕并完成身份验证时。我不知道解决方案是什么,但我认为错误的是,我不知道如何使用did挂载:D我寻找did挂载,但我不知道如何使用它,更重要的是,我必须找出它是如何工作的
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;
我找到了!!!问题是,当我的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;
函数使useffect()
Hook的依赖项在每次渲染时发生更改。将其移动到useffect
回调中。或者,您可以将onAuthStateChanged
的定义包装在它自己的useCallback()
Hook中。
更新的代码为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>
);
}
}
内存泄漏通常是什么时候会发生,你在异步函数之后,你的组件被卸载,更新你的状态。
家
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;
此外,如果您在任何时候都看到此警告,您可以使用处理该警告的方法。