为什么我的导航引用在带有 Redux 的 React Navigation 6 中还没有准备好?

Dᴀʀ*_*ᴅᴇʀ 5 react-native redux react-navigation react-navigation-v6

在 React Navigation 6 中,我的研究表明,要在没有 prop 的情况下进行导航,我应该参考并使用createNavigationContainerRef. 我可以将屏幕名称传递给我dispatch,但由于某种原因,当我评估病情时,isReady我总是被告知事实并非如此。代码:

应用程序.js:

import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import 'react-native-gesture-handler'

// Provider
import { Provider as AuthProvider } from './src/context/AuthContext'

// Navigation
import { navigationRef } from './src/navigation/NavRef'

// Screens
import ResolveAuthScreen from './src/screens/ResolveAuthScreen'

const App = () => {
  return (
    <AuthProvider>
      <NavigationContainer ref={navigationRef}>
        <ResolveAuthScreen />
      </NavigationContainer>
    </AuthProvider>
  )
}

export default App
Run Code Online (Sandbox Code Playgroud)

ResolveAuthScreen.js:

import React, { useEffect, useContext } from 'react'

// Context
import { Context as AuthContext } from '../context/AuthContext'

const ResolveAuthScreen = () => {
  const { tryLocalSignIn } = useContext(AuthContext)

  useEffect(() => {
    tryLocalSignIn()
  }, [])

  return null
}
export default ResolveAuthScreen
Run Code Online (Sandbox Code Playgroud)

AuthContext.js(精简):

import AsyncStorage from '@react-native-async-storage/async-storage'

// Context
import createContext from './createContext'

// Nav
import * as NavRef from '../navigation/NavRef'

const authReducer = (state, action) => {
  switch (action.type) {
    case 'signin':
      return { errorMessage: '', token: action.payload }
    case 'clear_error':
      return { ...state, errorMessage: '' }
    default:
      return state
  }
}

const tryLocalSignIn = dispatch => async () => {
  const token = await AsyncStorage.getItem('token')
  console.log({ token }) // renders token
  if (token) {
    dispatch({ type: 'signin', payload: token })
    NavRef.navigate('TrackListScreen')
  } else {
    NavRef.navigate('SignUp')
  }
}

export const { Provider, Context } = createContext(
  authReducer,
  { tryLocalSignIn },
  { token: null, errorMessage: '' },
)
Run Code Online (Sandbox Code Playgroud)

NavRef.js:

import { createNavigationContainerRef } from '@react-navigation/native'

export const navigationRef = createNavigationContainerRef()

export function navigate(name, params) {
  console.log({ name, params })
  if (navigationRef.isReady()) {
    console.log('ready')
    console.log({ name, params })
    navigationRef.navigate('TrackDetailScreen', { name, params })
  } else {
    console.log('not ready')
  }
}
Run Code Online (Sandbox Code Playgroud)

当我记录token来自调度时,我取回了令牌。当我记录屏幕时,我会返回TrackListScreennavigate但每当它被触发时,它总是返回not ready.

文件:

"dependencies": {
    "@react-native-async-storage/async-storage": "~1.15.0",
    "@react-navigation/bottom-tabs": "^6.0.9",
    "@react-navigation/native": "^6.0.6",
    "@react-navigation/native-stack": "^6.2.5",
    "axios": "^0.24.0",
    "expo": "~43.0.0",
    "expo-status-bar": "~1.1.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.2",
    "react-native-elements": "^3.4.2",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-reanimated": "~2.2.0",
    "react-native-safe-area-context": "3.3.2",
    "react-native-screens": "~3.8.0",
    "react-native-web": "0.17.1"
  },
Run Code Online (Sandbox Code Playgroud)

为什么我的navigate在我之后不起作用dispatch或者为什么是isReady假的?

小智 2

我有同样的问题。当尝试从 redux-saga 文件访问导出的 navigationRef.isReady() 时,它总是返回 false。我不确定这是一种安全的方法,也没有正确测试过这一点,但以下解决方法似乎对我有用:

应用程序.js

import {setNavigationRef, navigationIsReady} from './NavigationService';

const navigationRef = useNavigationContainerRef();

return (
      <NavigationContainer 
          ref={navigationRef}
          onReady={() => {
              setNavigationRef(navigationRef);
          }}> 
          ...
      </NavigationContainer>
);
Run Code Online (Sandbox Code Playgroud)

导航服务.js

export let navigationRefCopy = undefined;

export function setNavigationRef(navigationRef) {
    navigationRefCopy = navigationRef;
}

export function navigationIsReady() {
    return navigationRefCopy?.isReady(); // returns true when called in a redux saga file.
}
Run Code Online (Sandbox Code Playgroud)