从React Navigation V4升级到V5 redux集成



我刚刚得到一个项目,我被告知要升级所有的软件包。目前我正试图将反应导航从V4升级到V5,但我遇到了一个障碍,我不知道如何在router.js结束时折射代码,或者在ReduxNavigation.jsReducers/NavigationReducer.js中的代码

old router.js(代码移到下面的app.tsx)

const defaultNavigationOptions = {
defaultNavigationOptions: {
headerStyle: ComponentStyles.Navigation.header,
}
}
const modalNavigatorConfig = {
cardStyle: {
opacity: 1
},
navigationOptions: {
initialRouteName: 'Authentication',
headerMode: 'screen'
}

}

const authStack = createStackNavigator(
{
Login: LoginScreen,
}, defaultNavigationOptions
)
const dashboardStack = createStackNavigator({
Dashboard: DashboardScreen,
}, defaultNavigationOptions)
const appStack = createBottomTabNavigator({
Dashboard: {
screen: dashboardStack,
navigationOptions: {
title: "Dashboard",
tabBarIcon: ({focused, tintColor}) => (
<Image
resizeMode='contain'
style={{width: 24, height: 24, tintColor: (focused ? null : tintColor) }}
source={require('@Images/tab-dashboard.png')}
/>
)
}
},
})
export const ModalStack = createSwitchNavigator(
{
Authentication: authStack,
App: appStack,
},
{
initialRouteName: 'Login',
...defaultNavigationOptions
}
)
// Unsure of how to refractor this in V5 <---------------------
export const ReactNavigationReduxMiddleware = createReactNavigationReduxMiddleware(
state => state.nav
)
export const App = createReduxContainer(ModalStack, 'root')
const mapStateToProps = state => ({
state: state.nav
})
const AppWithNavigationState = connect(mapStateToProps)(App)
export default AppWithNavigationState

应用程序。(路由器在app.tsx中,因为我不知道如何把它放在一个单独的router.js文件中)

const appStack = createStackNavigator();
const Tab = createBottomTabNavigator();
function appStack() {
return (
<appStack.Navigator initialRouteName="Authentication">
<appStack.Screen name="Authentication" component={AuthLoadingScreen} options={{headerShown: false}} />
<appStack.Screen name="Login" component={LoginScreen} options={{headerShown: false}} />
<appStack.Screen name="Dashboard" component={DashboardScreen} />
</DashboardStack.Navigator>
);
}
function TabsStack() {
return (
<Tab.Navigator>
<Tab.Screen
name="Dashboard"
component={appStack}
options={{
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
)
}
const App = () => {
return (
<>
<Provider store={store}>
<StatusBar barStyle="dark-content" />
<NavigationContainer>
<TabsStack />
</NavigationContainer>
</Provider>
</>
);
};
export default App;

我不确定如何折射这个。这在V5中可能吗?

ReduxNavigation.js

class ReduxNavigation extends React.Component {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { nav, dispatch } = this.props;
if (nav.index === 0) {
return false;
}
if (nav.routes) {
const currentRouteName = nav.routes[nav.index].routeName;
if (currentRouteName === 'PAudit' || currentRouteName === 'PInit') {
return true;
}
}
dispatch(NavigationActions.back());
return true;
};
render() {
const { nav, dispatch } = this.props;
return <App state={nav} dispatch={dispatch} />;
}
}
const mapStateToProps = state => ({
nav: state.nav
});
export default connect(mapStateToProps)(ReduxNavigation);

Reducers/NavigationReducer.js (getActionForPathAndParams在V5中已弃用,我找不到类似的函数)

import { ModalStack } from '@Components/Router'
const { router } = ModalStack
const firstAction = router.getActionForPathAndParams('Authentication') // getActionForPathAndParams is deprecated in V5
const tempNavState = router.getStateForAction(firstAction)
/* ------------- Initial State ------------- */
export const INITIAL_STATE = router.getStateForAction(tempNavState)
export const reducer = (state = INITIAL_STATE, action) => {
const nextState = router.getStateForAction(action, state)
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state
}
export default reducer

存储
export default store = Reactotron.createStore(
rootReducer,
{},
compose(
applyMiddleware(ReduxThunk),
applyMiddleware(ReactNavigationReduxMiddleware)
)
)

异径接头/index.js

const appReducer = combineReducers({
nav: NavigationReducer,
})
const { Types, Creators: Actions } = createActions({
resetApp: []
})
const rootReducer = createReducer([], {
[Types.RESET_APP]: (state, action) => {
return appReducer(undefined, action)
//Passing undefined as state will make all the reducers using their initial states.
},
[ReduxSauceTypes.DEFAULT]: (state, action) => {
return appReducer(state, action)
}
})
const resetReduxStore = () => {
return dispatch => {
dispatch(Actions.resetApp())
}
}
export { rootReducer, resetReduxStore }

package.json

"react-navigation": "^4.4.3",
"react-navigation-redux-helpers": "^4.0.1",
"react-navigation-stack": "^2.10.2",
"react-navigation-tabs": "^2.10.1",
"redux": "^4.0.1",
"react-redux": "^7.2.2",
"redux-persist": "^5.6.6",
"redux-thunk": "^2.2.0",
"reduxsauce": "^0.7.0",

如何在redux中存储导航状态的简单答案是DON'T.

当前版本的React Navigation使这个非常显式

我也可以在Redux中存储导航状态吗?

这不可能。我们不支持它,因为它太容易搬起石头砸自己的脚,减慢/破坏你的应用程序。

他们提供了一些关于使用redux中的值来向navigate函数传递参数的建议。

你在代码中看到的是旧版本React导航的一个特性,但它总是被建议不要这样做。甚至是版本1。X文档显示

警告!

您可能不需要这样做!如果你不知道自己在做什么,在你自己的Redux存储中存储你的React导航状态可能会给你带来非常困难的时间。例如,你失去了React Navigation可以为你做的一些性能优化。请不要将您的状态集成到Redux中,除非首先确保您可以在没有它的情况下做您需要做的事情!

你需要在你的应用程序中找到任何从redux访问导航状态的地方,并重构它们,让它们使用props和hook直接从React导航中访问它。

最新更新