【问题标题】:React native Redux with Navigation issues用导航问题反应原生 Redux
【发布时间】:2020-09-01 22:44:29
【问题描述】:

我最近开始使用 React Native 进行编程,并且刚刚接触到 Navigations,它们非常酷且功能强大。但是,作为初学者,我遇到了一些问题。我正在使用 Redux 来管理状态,并且我有一个导航堆栈,它应该只在登录状态处于活动状态时呈现。这是代码的一个小sn-p。

const RootStackScreen = () => (
  <RootStack.Navigator headerMode="none">
    {initialState.loggedIn ? (
      <RootStack.Screen name="Application" component={TabScreen} />
    ) : (
      <RootStack.Screen name="Authentication" component={AuthStackScreen} />
    )}
  </RootStack.Navigator>
);

正如您在此处看到的,我的 RootStack 中有两个屏幕,我的身份验证屏幕,然后是我的主应用屏幕。我只是想说嘿,如果loggedIn 状态为真,则呈现应用程序,否则呈现身份验证屏幕。问题是,当我通过登录页面使用 redux 更改状态时,它会更新但不会更改页面。为方便起见,我还附上了我的 redux initialState 和 reducer

const initialState = {
  action: "",
  loggedIn: false,
  username: null,
  isLoading: false,
  failedLogin: "",
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "USER_LOGIN_GOOD":
      return { loggedIn: true };
    case "USER_LOGIN_FAIL":
      return { failedLogin: "Login Failed, Please try again" };
    default:
      return state;
  }
};

我试过说initialState.loggedInloggedIn,但由于某种原因,当它通过另一个页面中的redux 更新时它不会更新值。我已经检查以确保通过简单地打印新值来更新值,所以我知道更新值不是问题,而只是 RootStack 感应到更新。

非常感谢!任何帮助都会很有用,因为我一直为此努力!!!

更新:我正在通过调用 Dispatch 从我的登录页面设置状态

function mapDispatchToProps(dispatch) {
  return {
    logInSuccess: () =>
      dispatch({
        type: "USER_LOGIN_GOOD",
      }),
    logInFailed: () =>
      dispatch({
        type: "USER_LOGIN_FAIL",
      }),
  };
}

我也刚刚尝试像这样将 initialState 传递到 RootStack 中

const RootStackScreen = (initialState) => ( CONTENT HERE )

但它仍然不起作用。再次,非常感谢您

【问题讨论】:

  • RootStackScreen 应该从 props 获取登录值。您能否发布更多为const RootStackScreen 设置initialState 的代码?
  • 帖子已更新!
  • 感谢更新,但我真正想要的是状态如何绑定到RootStackScreen。在 redux 中,您应该将所有值设置到存储中,然后通过将它们连接到存储(通过 hooksor HoC)从组件中访问它们。您是否尝试直接在您的根屏幕中访问initialState

标签: reactjs react-native redux react-redux navigation


【解决方案1】:

对于根据反应导航文档的这种情况,您不应该在您放置堆栈导航器等的组件中执行任何条件。

更好的方法是先制作启动画面,这通常在每个应用程序中都有。

将其设为初始路由,然后对要显示的页面进行逻辑计算,例如:

<Stack.Navigator
          initialRouteName="SplashScreen"
          >
          <Stack.Screen name="Login" component={LoginScreen} />
          <Stack.Screen name="SplashScreen" component={SplashScreen} />
          <Stack.Screen name="Home" component={Home} />
        </Stack.Navigator>

所以这里的 Splashscreen 是初始路线,在 Splashscreen 中你喜欢:

class SplashScreen extends .. {

...
componentDidMount(){
isLoggedIn?this.props.navigation.navigate('Home'):this.props.navigation.navigate('Login')
}

}

希望对您有所帮助。如有疑问,请随意

【讨论】:

  • 好的,所以我尝试了这个,它有点工作。由于用户未登录,因此需要先登录 Splash。但是,现在的问题是,当我从登录屏幕更新 isLoggedIn 时,它不会转到主屏幕。
  • 所以我发现我只需要手动将this.props.navigation.navigate("Application"); 放入登录成功功能中。这是一个好习惯吗?
  • 很好,你成功了。如果你觉得我的回答有帮助。你可以投票。谢谢
  • 您能否发布一个指向说明在根导航中条件是不好的做法的文档的链接?根据此链接reactnavigation.org/docs/nesting-navigators 它实际上是可以的。我想知道在这种情况下最佳做法是什么。谢谢!
【解决方案2】:

@内森·贝莱特

在根堆栈中,您不应该有 if-else 语句兄弟。您的第一个初始路由应该是Authentication。我认为您可以将其更新为这样。

const RootStackScreen = () => (
  <RootStack.Navigator headerMode="none" initialRouteName="Authentication">
      <RootStack.Screen name="Application" component={TabScreen} />
      <RootStack.Screen name="Authentication" component={AuthStackScreen} />
    )}
  </RootStack.Navigator>
);

然后在文件 AuthStackScreen.js 中你应该处理逻辑来检查用户是否已经登录。这是示例代码:

import {useDispatch, useSelector, useStore} from 'react-redux'

export const SignInScreen = ({navigation}: SignInProps): ReactElement => {
  const dispatch = useDispatch()
  const appState = useStore().getState()
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    if (appState.loggedIn) {
      navigation.replace('Application')
    }

    setLoading(false)
  }, [])

  if (loading) return <LoadingScreen />

  return <YOUR_COMPONENT>

}

我希望这对你有所帮助?你有一些想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-22
    • 2019-05-19
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多