安装
Copy npm install react-navigation @rematch/react-navigation
对于 @rematch/core@0.x 使用 @rematch/react-navigation@1.1.0
示例
参看一个例子
设置
使用Redux设置React-Navigation是一个多步骤过程。 希望这个插件简化了这个过程。
创建你的<Routes />
,然后选择你的 initialRouteName
的名称。
Copy // Routes.js
export default StackNavigator (
{
Landing : {
screen : Screen .Landing ,
} ,
Login : {
screen : Screen .Login ,
} ,
App : {
screen : App ,
} ,
} ,
{
initialRouteName : 'Landing' ,
}
)
2. 传递 Routes
和 initialRouteName
进入 createReactNavigationPlugin
Copy // index.js
import { init , dispatch } from '@rematch/core'
import createReactNavigationPlugin from '@rematch/react-navigation'
import * as ReactNavigation from 'react-navigation'
import Routes from './Routes'
// add react navigation with redux
const { Navigator , reactNavigationPlugin } = createReactNavigationPlugin ({
Routes ,
initialScreen : 'Landing'
})
const store = init ({
plugins : [reactNavigationPlugin] ,
})
export default () => (
< Provider store = {store}>
< Navigator />
</ Provider >
)
3. 使用包含 navigation helpers 的插件来简化派发 Navigation action。
Copy // included in plugin
dispatch . nav . navigate = (action) => dispatch ( NavigationActions .navigate (action))
dispatch . nav . reset = (action) => dispatch ( NavigationActions .reset (action))
dispatch . nav . back = (action) => dispatch ( NavigationActions .back (action))
dispatch . nav . setParams = (action) => dispatch ( NavigationActions .setParams (action))
4. 只需传递 NavigationAction
选项即可。
Copy // somewhere in your app
import { dispatch } from '@rematch/core'
dispatch . nav .navigate ({ routeName : 'Login' })
如有必要,导入NavigationActions
。
Copy import { dispatch } from '@rematch/core'
import { NavigationActions } from 'react-navigation'
const resetAction = dispatch . navigate .reset ({
index : 1 ,
actions : [
NavigationActions .navigate ({ routeName : 'Profile' }) ,
NavigationActions .navigate ({ routeName : 'Settings' })
]
})
Back Handler
使用react-navigation设置Android后退按钮处理的示例。
Copy import { dispatch , init } from '@rematch/core'
import createReactNavigation from '@rematch/react-navigation'
import React from 'react'
import { BackHandler } from 'react-native'
import { Provider } from 'react-redux'
import { Routes } from './Routes'
export class App extends React . Component {
componentDidMount () {
BackHandler .addEventListener ( 'hardwareBackPress' , this .handleBack)
}
componentWillUnmount () {
BackHandler .removeEventListener ( 'hardwareBackPress' , this .handleBack)
}
handleBack = () => {
if ( store .getState (). nav .index === 0 ) {
BackHandler .exitApp ()
}
dispatch . nav .back ()
return true
}
render () {
return (
< Provider store = {store}>
< Navigator />
</ Provider >
);
}
}
Selectors
你可能会发现将一些自定义selector添加到你的nav model
是有帮助的。您可以通过创建一个nav model
配置对象来轻松添加selector。这个例子将添加一个currentRouteName
选择器:
Copy // models/nav.js
export default {
selectors : {
currentRouteName (state) { return state .routes[ state .index].routeName; } ,
} ,
}
将上面的 model 添加到您的Rematch配置中:
Copy // models/index.js
export { default as nav } from './nav'
确保您的新 model 包含在您的init
中:
Copy import { select } from '@rematch/select'
import * as models from './models'
const store = init ({
models ,
plugins : [select , reactNavigationPlugin] ,
});
当然,你还需要安装 Rematch Select 插件 。
现在你将有能力在你的app内调用select.nav.currentRouteName(state)
,参阅 Rematch Select 插件文档 以获取更多关于配置和使用的selector。
Immutable JS and other non-{ } Stores
如果您的 store 不是标准的Javascript对象{}
,那么您可能需要将 sliceState
配置传递给createReactNavigationPlugin
。该函数获取状态并返回包含React Navigation对象的状态片段。它在Navigator
中用于将 state 映射到其属性,并用于侦听 navigation state 更改的中间件。默认情况下使用state.nav
,在大多数情况下它可以正常工作。
如果你的 store 是一个 Immutable JS 对象,你可能需要传递 sliceState: state => state.get('nav')
作为 createReactNavigationPlugin
的配置。这里有一个小例子:
Copy // index.js
import { init , dispatch } from '@rematch/core'
import createReactNavigationPlugin from '@rematch/react-navigation'
import * as ReactNavigation from 'react-navigation'
import Routes from './Routes'
import { combineReducers } from 'redux-immutable' ;
import { Map } from 'immutable' ;
// add react navigation with redux
const { Navigator , reactNavigationPlugin } = createReactNavigationPlugin ({
Routes ,
initialScreen : 'Landing' ,
sliceState : state => state .get ( 'nav' ) // Returns Immutable JS slice
})
const store = init ({
initialState : fromJS ({}) ,
plugins : [reactNavigationPlugin] ,
redux : {
initialState : Map () , // Initializes a blank Immutable JS Map
combineReducers : combineReducers , // Combines reducers into Immutable JS collection
} ,
})
export default () => (
< Provider store = {store}>
< Navigator />
</ Provider >
)
在上面的例子中,你的 store 是一个Immutable JS对象。但是,商店的nav
切片是标准的 JS 对象。我推荐这种方法,因为 React Navigation 导航器和 Redux 中间件期望导航状态是一个标准的 JS 对象。这是最高效的方法。另一种方法是将导航状态存储为不可变 JS 映射,每次导航器或中间件需要访问 Rematch 状态时都需要调用 fromJS()
和 toJS()
,这会导致性能下降。