Reactjs 反应导航不';t在redux状态更改后更改导航屏幕
即使redux状态更改,导航也不会更改为MainScreen。我已经验证了authState从{“isAuthenticated”:false,“isLoading”:true,“token”:null}更改为{“isAuthenticated”:true,“isLoading”:false,“token”:“some_token”},但是导航页面停留在登录页面(在LandingNavigator内),而不是转到MainNavigator AppNavigation.jsReactjs 反应导航不';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
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(
...