状态更改后,React Native不重新渲染

时间:2020-06-01 10:50:32

标签: react-native reducers context-api

我试图使用上下文api和reducer进行身份验证流程, 我有一个名为GlobalState的文件,其中使用令牌保留了所有身份验证状态。我也有用reducer来更新状态。 在我的GlobalState文件中,有一个函数loginFb,它将根据我的rest API的响应来更新状态。 当我尝试控制状态时,我可以看到登录后状态已更改,但是我的应用程序未重新呈现。我期望我的应用在状态更改时重新呈现,并移至HomeStackScreens。

以下是我的app.js

import 'react-native-gesture-handler';
import React, {useContext} from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createMaterialBottomTabNavigator} from '@reactnavigation/material-bottom-tabs';
import {createStackNavigator} from '@react-navigation/stack';
import AsyncStorage from '@react-native-community/async-storage';
import HomeTabs from './screens/HomeTabs';
import Login from './screens/Login';
import {GlobalContext, GlobalProvider} from './context/GlobalState';

const AuthStack = createStackNavigator();
const HomeStack = createStackNavigator();

const AuthStackScreen = () => {
  return (
    <AuthStack.Navigator screenOptions={{}}>
      <AuthStack.Screen name="Login" component={Login} />
    </AuthStack.Navigator>
  );
};

const HomeStackScreens = () => {
  return (
    <HomeStack.Navigator
      screenOptions={{
        headerTintColor: 'white',
        headerStyle: {backgroundColor: '#37966f', elevation: 0},
      }}>
      <HomeStack.Screen name="Home" component={HomeTabs} />
    </HomeStack.Navigator>
  );
};

function App() {


  React.useEffect(() => {
    // Fetch the token from storage then navigate to our appropriate place
    const bootstrapAsync = async () => {
      let userToken;
      console.log('is Signedin :', isSignedIn);

      try {
        userToken = await AsyncStorage.getItem('authTocken');
        if (userToken) console.log('autTocken:' + userToken);
        else console.log('no tocken');
      } catch (e) {

        console.log('no tocken');
      }


    };

    bootstrapAsync();
  }, []);
  const {authState, isSignedIn} = useContext(GlobalContext);
  return (
    <GlobalProvider>
      <NavigationContainer>
        {console.log('from app:', authState, 'signedin', isSignedIn)}
        {isSignedIn ? <HomeStackScreens /> : <AuthStackScreen />}
      </NavigationContainer>
    </GlobalProvider>
  );
}

export default App;

Globalstate.js

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

//Initial State

const initialState = {
  authTocken: '',
  refreshTocken: '',
  fbToken: '',
  isSignedIn: false,
};

export const GlobalContext = createContext(initialState);
export const GlobalProvider = ({children}) => {
  const [authState, dispatch] = useReducer(AppReducer, initialState);

  async function loginFb(fbToken) {
    // loginFb: async fbToken=>{
    await fetch(
      'https://api_url?accessToken=' +
        fbToken,
      {
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
      },
    )
      .then((resp) => resp.json())
      .then(async function (data) {
        await AsyncStorage.setItem('authTocken', data.token);
        await AsyncStorage.setItem('refreshTocken', data.refreshToken);
        await AsyncStorage.setItem('fbToken', fbToken);
        dispatch({
          type: 'SIGN_IN',
          payload: data,
        });
      })
      .catch((error) => {
        console.log('found error', error);
      });
  }
  return (
    <GlobalContext.Provider
      value={{authState, loginFb, isSignedIn: authState.isSignedIn}}>
      {children}
    </GlobalContext.Provider>
  );
};

AppReducer.js

export default (state, action) => {
  switch (action.type) {
    case 'SIGN_IN': {
      return {
        ...state,
        isSignedIn: true,
        refreshTocken: action.payload.refreshToken,
        authTocken: action.payload.token,
      };
    }

    default:
      return state;
  }
};

1 个答案:

答案 0 :(得分:1)

代替

export default App;

更改为

export default () => (
  <GlobalProvider>
     <App />
   </GlobalProvider>
    )

现在可以正常使用