useContext дает свойство состояния undefined TypeError в собственном ответе - PullRequest
0 голосов
/ 02 августа 2020

Недавно я начал изучать React Context и ловушку и соответственно обновлять существующее приложение. Но столкнулся с проблемой, которую я не могу решить. Когда я использую useContext в своем компоненте, он выдает мне эту ошибку TypeError: Cannot read property 'state' of undefined, я весь день искал в Интернете и пересмотрел еще несколько серий руководств, но не мог понять, в чем проблема, с которой я столкнулся, и как ее решить. Это. Так что, если кто-нибудь из вас, ребята, поможет мне с этим, это будет действительно полезно для меня. Вот мой код:

context. js

import React, { createContext, useReducer } from "react";
import AsyncStorage from '@react-native-community/async-storage';

export const AuthContext = createContext();

const initialState = {
    isLoading: true,
    newSession: false,
    userToken: null
};

const createActions = dispatch => ({
    signInPage: data => {
        dispatch({ type: 'SIGN_IN_PAGE' });
    },
    signInAction: async data => {
        const { student_id, password, database_name, site_url} = data;

        if (student_id && password && database_name) {
            // validating the login credential through api
        }
    },
    signOut: async data => {
        await AsyncStorage.removeItem('user_token');

        dispatch({ type: 'SIGN_OUT' });
    },
    newSession: data => {
        dispatch({ type: 'NEW_SESSION' });
    },
    loading: data => {
        dispatch({ type: 'LOADING' });
    }
});


const reducer = (state, action) => {
    switch (action.type) {
        case 'LOADING':
            return {
                ...state,
                isLoading: true,
                newSession: false,
                userToken: null
            };
        case 'SIGN_IN_PAGE':
            return {
                ...state,
                newSession: false,
                isLoading: false,
                userToken: null
            };
        case 'SIGN_IN_ACTION':
            return {
                ...state,
                isValidating: false,
                newSession: false,
                isLoading: false,
                userToken: action.token,
            };
        case 'SIGN_OUT':
            return {
                ...state,
                newSession: true,
                isLoading: false,
                userToken: null,
            };
        case 'NEW_SESSION':
            return {
                ...state,
                newSession: true,
                isLoading: false,
                userToken: null
            };
        case 'RESTORE_TOKEN':
            return {
                ...state,
                newSession: false,
                isLoading: false,
                userToken: action.token
            };
        default:
            return state;
    }
};


const AuthProvider = (props) => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const actions = createActions(dispatch);

    return (
        <AuthContext.Provider value={{ state, ...actions }}>
            {props.children}
        </AuthContext.Provider>
    );
}

export default AuthProvider;

App. js

//packages
import React, { useContext } from 'react';


// third party packages
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import AsyncStorage from '@react-native-community/async-storage';
import { openDatabase } from 'react-native-sqlite-storage';
import {
    createDrawerNavigator,
    DrawerContentScrollView,
    DrawerItemList,
    DrawerItem
} from '@react-navigation/drawer';


// <----- assets and components ----->
import AuthProvider, { AuthContext } from './screens/context';
import BottomTabCotainer from './screens/tab/BottomTabContainer.js';

// drawer components
import { EditProfileScreen } from './screens/drawer/EditProfileScreen.js';
import { ChangePasswordScreen } from './screens/drawer/ChangePasswordScreen.js';

// stack components
import { OnlineClassroomScreen } from './screens/OnlineClassroomScreen.js';
import { InstituteCodeScreen } from './screens/InstituteCodeScreen.js';
import { LoginScreen } from './screens/LoginScreen.js';
import { NewSessionScreen } from './screens/NewSessionScreen.js';
import LoadingScreen from './screens/LoadingScreen.js';
// <!----- assets and components ----->


var db = openDatabase({ name: 'UserDatabase.db' });

const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();


function CustomDrawerContent(props) {
    const { signOut } = useContext(AuthContext);

    return (
        <DrawerContentScrollView {...props}>
            <DrawerItemList {...props} />
            <DrawerItem label="Logout" onPress={signOut} />
        </DrawerContentScrollView>
    );
}


export default function App() {

    const { state } = useContext(AuthContext);

    React.useEffect(() => {
        // Fetch the token from storage then navigate to our appropriate place
        const bootstrapAsync = async () => {
            let userToken;

            try {
                userToken = await AsyncStorage.getItem('user_token');

                if (userToken) {
                    await AsyncStorage.getItem('expire_at', async (err, value) => {
                        if (value !== null && new Date(value) < (new Date())) {
                            newSession();
                        } else {
                            dispatch({ type: 'RESTORE_TOKEN', token: userToken });
                        }
                    });
                } else {
                    new Promise((resolve, reject) => {
                        // creating users table
                        db.transaction(function (txn) {
                            txn.executeSql(
                                "SELECT name FROM sqlite_master WHERE type='table' AND name='users'",
                                [],
                                function (tx, res) {
                                    if (res.rows.length == 0) {
                                        txn.executeSql(
                                            'DROP TABLE IF EXISTS users',
                                            [],
                                            function(tx, res) {
                                                console.log('table dropped');
                                            }
                                        );
                                        txn.executeSql(
                                            'CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY AUTOINCREMENT, full_name VARCHAR(100), username VARCHAR(100), password VARCHAR(100), site_url VARCHAR(100), database_name VARCHAR(50), image_location VARCHAR(100) NULL)',
                                            [],
                                            function(tx, res) {
                                                console.log('table created');
                                                resolve(res);
                                            }
                                        );
                                    } else {
                                        resolve(res);
                                    }
                                }
                            );
                        });
                    });

                    db.transaction(function (txn) {
                        txn.executeSql(
                            "SELECT * from users",
                            [],
                            function(tx, res) {
                                if (res.rows.length > 0) {
                                    newSession();
                                } else {
                                    signInPage();
                                }
                            }
                        );
                    });
                }
            } catch (e) {
                // Restoring token failed
            }
        };

        bootstrapAsync();
    }, []);


    return (
        <AuthProvider>
            <NavigationContainer>
                {state.isLoading ? (
                    <Stack.Navigator>
                        <Stack.Screen name="Loading" component={LoadingScreen} options={{ headerShown: false }} />
                    </Stack.Navigator>
                ) : state.newSession ? (
                    <Stack.Navigator>
                        <Stack.Screen name="NewSession" component={NewSessionScreen} options={{ headerShown: false }} />
                        <Stack.Screen name="InstituteCode" component={InstituteCodeScreen} options={{ headerShown: false }} />
                        <Stack.Screen name="Login" component={LoginScreen} options={{ headerShown: false }} />
                    </Stack.Navigator>
                ) : state.userToken == null ? (
                    <Stack.Navigator>
                        <Stack.Screen name="InstituteCode" component={InstituteCodeScreen} options={{ headerShown: false }} />
                        <Stack.Screen name="Login" component={LoginScreen} options={{ headerShown: false }} />
                    </Stack.Navigator>
                ) : (
                    <Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}>
                        <Drawer.Screen name="Dashboard" component={BottomTabCotainer} />
                        <Drawer.Screen name="Edit Profile" component={EditProfileScreen} />
                        <Drawer.Screen name="Change Password" component={ChangePasswordScreen} />
                        <Drawer.Screen name="OnlineClass" component={OnlineClassroomScreen} options={{ headerShown: false }} />
                    </Drawer.Navigator>
                )}
            </NavigationContainer>
        </AuthProvider>
    );
}

1 Ответ

1 голос
/ 02 августа 2020

App должен быть потомком AuthProvider, т.е.

<AuthProvider>
 <App/>
<AuthProvider/>

Вы не можете получить к нему доступ, если вы визуализируете его внутри самого компонента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...