React Native-违反不变量,对象作为React子对象无效



我正在使用Expo在React原生环境中制作应用程序,在尝试使用我制作的的ContextProvider构建身份验证服务时遇到了问题

这是我的App.js代码

App.js:

import * as React from 'react';
import { AsyncStorage, StatusBar, Platform,  Button, Text, TextInput, View, StyleSheet } from 'react-native';
import { SplashScreen } from 'expo';
import * as Font from 'expo-font';
import { Ionicons } from '@expo/vector-icons';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
//SCREENS
import BottomTabNavigator from './navigation/BottomTabNavigator';
import LoginScreen  from './screens/Auth/Login';
import RegisterScreen  from './screens/Auth/Register';
//SCREENS

import AuthContext from "./contexts/AuthContext"
const Stack = createStackNavigator();
import useLinking from './navigation/useLinking';

export default function App(props) {
const [LOGGED_IN, setLOGGED_IN] = React.useState(false);
const [isLoadingComplete, setLoadingComplete] = React.useState(false);
const [initialNavigationState, setInitialNavigationState] = React.useState();
const containerRef = React.useRef();
const { getInitialState } = useLinking(containerRef);
const [state] = React.useReducer({
isLoading: false
});
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('isLogin');
if (value) {
setLOGGED_IN(value)
}
console.log('isLogin is false');
} catch (error) {
}
};
const authContext = React.useMemo(() => ({
isLogin: async data => {
setLOGGED_IN(data.LOGGED_IN)
}
}),[]
);

// Load any resources or data that we need prior to rendering the app
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHide();
setInitialNavigationState(await getInitialState());
await Font.loadAsync({
...Ionicons.font,
'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf'),
});
} catch (e) {
console.warn(e);
} finally {
setLoadingComplete(true);
SplashScreen.hide();
}
}
loadResourcesAndDataAsync();
_retrieveData();
if (!isLoadingComplete && !props.skipLoadingScreen) {
return null;
} else {
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer ref={containerRef} initialState={initialNavigationState}>
{ LOGGED_IN ? (
<Stack.Navigator>
<Stack.Screen name="Root" component={BottomTabNavigator} /> 
</Stack.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen name="Login" options={{headerShown: false}} component={LoginScreen} />
<Stack.Screen name="Register" options={{headerShown: true}} component={RegisterScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
</AuthContext.Provider>
);
}
}

AuthContext.js:

import React from "react";
const AuthContext = React.createContext({
isLoggedIn: () => {},
signIn: () => {},
signOut: () => {}
})
export default AuthContext;

当我在Expo-cli的登录页面上运行该应用程序,并更改代码中的某些内容并保存它时,应用程序刷新,我得到了以下错误:

Objects are not valid as a React child (found: object with keys {_40, _65, _55, _72}). If you meant to render a collection of children, use an array instead.
in Login (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at CardContainer.tsx:187)
in RCTView (at CardContainer.tsx:186)
in RCTView (at Card.tsx:508)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:491)
in PanGestureHandler (at Card.tsx:484)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:480)
in RCTView (at Card.tsx:473)
in Card (at CardContainer.tsx:154)
in CardContainer (at CardStack.tsx:518)
in RCTView (at CardStack.tsx:109)
in MaybeScreen (at CardStack.tsx:511)
in RCTView (at CardStack.tsx:92)
in MaybeScreenContainer (at CardStack.tsx:410)
in CardStack (at StackView.tsx:384)
in KeyboardManager (at StackView.tsx:382)
in RNCSafeAreaView (at src/index.tsx:26)
in SafeAreaProvider (at SafeAreaProviderCompat.tsx:42)
in SafeAreaProviderCompat (at StackView.tsx:379)
in RCTView (at StackView.tsx:378)
in StackView (at createStackNavigator.tsx:67)
in StackNavigator (at App.js:89)
in EnsureSingleNavigator (at BaseNavigationContainer.tsx:267)
in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:39)
in ThemeProvider (at NavigationContainer.tsx:38)
in ForwardRef(NavigationContainer) (at App.js:83)
in App (at withExpoRoot.js:26)
in RootErrorBoundary (at withExpoRoot.js:25)
in ExpoRoot (at renderApplication.js:40)
in RCTView (at AppContainer.js:101)
in RCTView (at AppContainer.js:119)
in AppContainer (at renderApplication.js:39)
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:9033:12 in <anonymous>
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:9029:4 in throwOnInvalidObjectType
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:10114:31 in reconcileChildFibers
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:12446:6 in reconcileChildren
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:13587:22 in mountIndeterminateComponent
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:307:15 in invokeGuardedCallbackImpl
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:531:36 in invokeGuardedCallback
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:20488:8 in beginWork$$1
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:19370:24 in performUnitOfWork
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:19347:39 in workLoopSync
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:18997:22 in renderRoot
* [native code]:null in renderRoot
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:18709:28 in runRootCallback
* [native code]:null in runRootCallback
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:5642:32 in runWithPriority$argument_1
- node_modulesschedulercjsscheduler.development.js:643:23 in unstable_runWithPriority
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:5638:22 in flushSyncCallbackQueueImpl
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:5627:28 in flushSyncCallbackQueue
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:18851:26 in flushSync
- node_modulesreact-nativeLibrariesRendererimplementationsReactNativeRenderer-dev.js:6416:14 in flushSync$argument_0
- node_modulesreact-refreshcjsreact-refresh-runtime.development.js:218:32 in mountedRoots.forEach$argument_0
* [native code]:null in forEach
- node_modulesreact-refreshcjsreact-refresh-runtime.development.js:210:25 in mountedRoots.forEach$argument_0
- node_modulesreact-nativeLibrariesCoresetUpReactRefresh.js:43:6 in Refresh.performReactRefresh
- node_modulesmetrosrclibpolyfillsrequire.js:609:10 in setTimeout$argument_0
- node_modulesreact-nativeLibrariesCoreTimersJSTimers.js:146:14 in _callTimer
- node_modulesreact-nativeLibrariesCoreTimersJSTimers.js:399:17 in callTimers
- node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:436:47 in __callFunction
- node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:111:26 in __guard$argument_0
- node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:384:10 in __guard
- node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:110:17 in __guard$argument_0
* [native code]:null in callFunctionReturnFlushedQueue

错误发生在(App.js(文件的(返回(部分,如错误日志中所示

编辑:此处Login.js文件:

import React from 'react';
import { View, ScrollView, Image, TouchableOpacity, Text, SafeAreaView, StyleSheet, TouchableWithoutFeedback, KeyboardAvoidingView, Keyboard, Platform, AsyncStorage } from 'react-native';
import { Feather } from '@expo/vector-icons';
import API from '../../components/Api';
import {Button, Input, InputCode, Spinner} from '../../components/AppComponents';
import {setStorage} from '../../components/Functions';
import AuthContext from "../../contexts/AuthContext"
import Colors from '../../constants/Colors';
export default function Login(props) {
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const [isRefresh, setIsRefresh] = React.useState(false);
const [LOGGED_IN, setLOGGED_IN] = React.useState(false);
const { isLogin } = React.useContext(AuthContext);
isLogin({LOGGED_IN});
Init = async () => {
var Login = await AsyncStorage.getItem('Login');
}

Login = async () => {
setIsRefresh(true);
if(username && password){
API.Login(username, password).then((res) => {
if(res.isLogin === 'true'){
setStorage('isLogin', toString(true));
setStorage('UID', res.user_id );    
setLOGGED_IN(true);
}else{
setStorage('isLogin','');
setStorage('UID', '');    
setIsRefresh(false);
setLOGGED_IN(false);
alert(res.msg);
}
}).catch((error)=>{ 
setIsRefresh(false);
alert(error)
}); 
}else{
alert('Complete los datos requeridos')
}
}
Init();
return (
<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : null} style={{ flex: 1 }}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<SafeAreaView style={styles.container}>
<View style={{ flex : .1}} />
<Spinner isLoading={isRefresh}/>

<View style={{ flex : 1}} >
<View style={styles.logoContent}>
<Image source={require('../../assets/images/logo_mini.png')} style={{width:160, height:120}} />
</View>
<View style={styles.forms}>
<Input label="Usuario" round
onChangeText={setUsername}
value={username}
placeholderTextColor="black" icon="user" iconColor="black" textColor="black" borderBottomColor="black"/>

<Input label="Contraseña" round
onChangeText={setPassword} 
value={password}
placeholderTextColor="black" icon="lock" iconColor="black" textColor="black" borderBottomColor="black" password={true} />
<View style={{width:'100%', height:'20%'}} />
</View>
<View style={{padding:25}} >
<Button title="INGRESAR"  onPress={()=>Login()} bg={Colors.primary} />
</View>
</View>

</SafeAreaView>
</TouchableWithoutFeedback>
<TouchableOpacity style={{alignItems:'center' , padding:20, position:'absolute', bottom:0, left:0, right:0}}  
onPress={()=>props.navigation.navigate('Register')} >
<Text>Registrarme</Text>
</TouchableOpacity>
</KeyboardAvoidingView>

);
}

const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20,
backgroundColor: Colors.primary,
},
forms:{    
flex: .5,
paddingHorizontal: 25,
},
formsCenter:{    
alignItems:'center',
},
logoContent:{
flex: .3,
marginBottom: 48,
alignItems:'center',
justifyContent: 'center',
},
selets:{
flexDirection:'row',
},
contentButton: {
backgroundColor: '#eee',
borderRadius:50,
margin:15,
height:50,
width:50,
textAlign:'center',
alignItems:'center',
justifyContent: 'center',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.22,
shadowRadius: 2.22,
elevation: 3,
},
contentButtonText: {
backgroundColor: '#eee',
margin:8,
width:30,
textAlign:'center',
alignItems:'center',
justifyContent: 'center',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.22,
shadowRadius: 2.22,
elevation: 3,
},  
buttonText: {
textAlign:'center',
fontSize: 28,
fontWeight: '700',
color:'#444'
},
buttonTextText: {
textAlign:'center',
fontSize: 20,
fontWeight: '700',
},  
});

这不是实现授权react-navigation的正确方法:

{ LOGGED_IN ? (
<Stack.Navigator>
<Stack.Screen name="Root" component={BottomTabNavigator} /> 
</Stack.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen name="Login" options={{headerShown: false}} component={LoginScreen} />
<Stack.Screen name="Register" options={{headerShown: true}} component={RegisterScreen} />
</Stack.Navigator>
)}

应该使用switchnavigator ,而不是像这样使用三元函数

最新更新