Reactjs 反应导航不';t在redux状态更改后更改导航屏幕

Reactjs 反应导航不';t在redux状态更改后更改导航屏幕,reactjs,react-native,react-redux,Reactjs,React Native,React Redux,即使redux状态更改,导航也不会更改为MainScreen。我已经验证了authState从{“isAuthenticated”:false,“isLoading”:true,“token”:null}更改为{“isAuthenticated”:true,“isLoading”:false,“token”:“some_token”},但是导航页面停留在登录页面(在LandingNavigator内),而不是转到MainNavigator AppNavigation.js const Navig

即使redux状态更改,导航也不会更改为MainScreen。我已经验证了authState从{“isAuthenticated”:false,“isLoading”:true,“token”:null}更改为{“isAuthenticated”:true,“isLoading”:false,“token”:“some_token”},但是导航页面停留在登录页面(在LandingNavigator内),而不是转到MainNavigator

AppNavigation.js

const Navigator = () => { 

  var [authStat, setAuthStat] = useState({})

  useEffect(()=> {
    var authState = store.getState().auth
    setAuthStat(authState)
  }, [authStat])
  console.log(authStat);


  if(authStat.isLoading){
    return(
      <Stack.Navigator>
      <Stack.Screen
        options={{headerShown: false}}
        name="Splash"
        component={ShowSplash}
      />
      </Stack.Navigator>
    )
  }
  else{
    return(
      <Stack.Navigator>
        { authStat.isAuthenticated ?
          (<Stack.Screen
            options={{headerShown: false}}
            name="Main"
            component={MainNavigator}
          />)
          :
          (<Stack.Screen options={{headerShown: false}} name="Landing" component={LandingNavigator} />)
          }
      </Stack.Navigator>
    )
  }

};
AuthReducer.js

/* eslint-disable comma-dangle */
const authState = {
    isLoading: true,
    isAuthenticated: false,
    token: null
  };
  
  export const authReducer = (state = authState, action) => {
    const newState = JSON.parse(JSON.stringify(state));
    switch (action.type) {
        case 'LOGIN_REQUEST': {
            return {
                isLoading: true, // Show a loading indicator.
                isAuthenticated: false
            }
        }
        case 'RESTORE_TOKEN': {
            return {
                isLoading: false, // Show a loading indicator.
                isAuthenticated: true,
                token: action.payload
            }
        }
        case 'LOGIN_FAILURE':
        return {
            isLoading: false,
            isAuthenticated: false,
            error: action.error
        }
        case 'LOGIN_SUCCESS':
        return {
            isLoading: false,
            isAuthenticated: true, // Dismiss the login view.
            token: action.payload
        }
        case 'LOGOUT': {
            return {
                isLoading: false, // Show a loading indicator.
                isAuthenticated: false,
                token: null
            }
        }
      default:
        return newState;
    }
  
    return newState;
  };
Auth.js

import AsyncStorage from '@react-native-async-storage/async-storage';
import { useDispatch } from 'react-redux';
import {loginRequest, loginSuccess, loginFailure, logOut} from '../redux/actions/authAction';

export const storeToken = async (value) => {
    try {
      await AsyncStorage.setItem('token', value)
    } catch (e) {
      // saving error
    }
  }

  export const getToken = async () => {
    try {
      const value = await AsyncStorage.getItem('token')
      if(value !== null) {
        return value
      } else{
          return null
      }
    } catch(e) {
      // error reading value
      console.log(e);
    }
  }

  export const removeToken = async () => {
    try {
      await AsyncStorage.removeItem('token')
    } catch(e) {
      // remove error
    }
    console.log('token removed.')
  }

  export const isLoggedIn = async () => {
    if(await getToken() != null){
        return true
    }
    return false
}

export const signOut = () => {
  removeToken()
}

export default {storeToken, getToken, removeToken, isLoggedIn, signOut }
LoginScreen.js

/* eslint-disable comma-dangle */
import React, { useEffect, useState, useCallback } from 'react';
import {
  View,
  TouchableHighlight,
  Text,
  TextInput,
  TouchableWithoutFeedback,
  Keyboard,
  ScrollView
} from 'react-native';
import {login} from '../../api/apiQueries'
import {storeToken} from '../../auth/auth'
import store from '../../redux/store';
import styles from './styles';

import { useDispatch, useSelector } from 'react-redux';
const authState = store.getState().auth;


const LogInScreen = ({route, navigation}) => {

  const [userName, setUserName] = useState("")
  const [password, setPassword] = useState("")

  const dispatch = useDispatch()

  onPressLogButton = () => {
    dispatch(login(userName, password))
  }

  return (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    <ScrollView style={styles.container}>
      <View>
        <Text style={styles.title}>Sign in</Text>
        <View style={styles.inputContainer}>
          <TextInput
            style={styles.input}
            placeholder="User Name"
            onChangeText={text => setUserName(text)}
            value={userName}
          />
        </View>
        <View style={styles.inputContainer}>
          <TextInput
            style={styles.input}
            placeholder="Password"
            onChangeText={text => setPassword(text)}
            value={password}
          />
        </View>
        <View style={styles.logContainer}>
          <TouchableHighlight
            style={styles.loginContainer}
            onPress={() => onPressLogButton()}
          >
            <Text style={styles.logTxt}>Log in</Text>
          </TouchableHighlight>
          {/* <Text style={styles.orTxt}>OR</Text> */}
          {/* <TouchableHighlight
            style={styles.facebookContainer}
            onPress={() => this.onPressFacebookButton()}
          >
            <Text style={styles.facebookTxt}>Facebook Login</Text>
          </TouchableHighlight> */}
        </View>
      </View>
    </ScrollView>
  </TouchableWithoutFeedback>
);


}

export default LogInScreen
/*eslint禁用逗号悬挂*/
从“React”导入React,{useffect,useState,useCallback};
进口{
看法
触控高光,
文本,
文本输入,
可触摸且无反馈,
键盘
卷轴视图
}从“反应本机”;
从“../../api/APIQuery”导入{login}
从“../../auth/auth”导入{storeToken}
从“../../redux/store”导入存储;
从“./styles”导入样式;
从'react redux'导入{useDispatch,useSelector};
const authState=store.getState().auth;
const LogInScreen=({route,navigation})=>{
const[userName,setUserName]=useState(“”)
const[password,setPassword]=useState(“”)
const dispatch=usedpatch()
onPressLogButton=()=>{
发送(登录名(用户名、密码))
}
返回(
Keyboard.disclose()}>
登录
setUserName(文本)}
值={userName}
/>
设置密码(文本)}
值={password}
/>
onPressLogButton()}
>
登录
{/*或*/}
{/*this.onPressFacebookButton()}
>
Facebook登录
*/}
);
}
导出默认登录屏幕

如评论中所述,解决方案是使用
useSelector
挂钩,或者使用
connect
方法的
MapStateTops
参数订阅组件以存储更新。这样,只要存储通过已调度的操作进行更新,它就会运行

从文档中:

useSelector()
还将订阅Redux应用商店,并运行 每当调度一个操作时,使用选择器

这意味着,例如,对于AppNavigation.js,您可以将代码更改为:

import { useSelector } from 'react-redux';

const Navigator = () => { 
    const authStat = useSelector((state) => state.auth);

    if(authStat.isLoading){
        return(
...

通过直接访问从应用商店读取数据就可以做到这一点,但这并不意味着订阅将来的更改。

您使用的是hook,您使用的是react-redux;您为什么不使用
useSelector
而不是直接访问存储并手动将存储详细信息复制到本地状态?这样,一旦redux状态改变,你就不会得到任何更新。黄金!我刚刚用redux store替换了本地状态,并使用了您提到的use selector,它起了作用。想知道使用getStore和useSelector获得商店有什么区别吗?请检查我的答案;如果你能接受,我将不胜感激。
import { useSelector } from 'react-redux';

const Navigator = () => { 
    const authStat = useSelector((state) => state.auth);

    if(authStat.isLoading){
        return(
...