React Navigation
安装
npm install react-navigation @rematch/react-navigation
对于 @rematch/core@0.x 使用 @rematch/react-navigation@1.1.0
示例
参看一个例子
设置
使用Redux设置React-Navigation是一个多步骤过程。 希望这个插件简化了这个过程。
创建你的
<Routes />
,然后选择你的initialRouteName
的名称。
// Routes.js
export default StackNavigator(
{
Landing: {
screen: Screen.Landing,
},
Login: {
screen: Screen.Login,
},
App: {
screen: App,
},
},
{
initialRouteName: 'Landing',
}
)
2. 传递 Routes
和 initialRouteName
进入 createReactNavigationPlugin
// 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。
// 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
选项即可。
// somewhere in your app
import { dispatch } from '@rematch/core'
dispatch.nav.navigate({ routeName: 'Login' })
如有必要,导入NavigationActions
。
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后退按钮处理的示例。
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
选择器:
// models/nav.js
export default {
selectors: {
currentRouteName(state) { return state.routes[state.index].routeName; },
},
}
将上面的 model 添加到您的Rematch配置中:
// models/index.js
export { default as nav } from './nav'
确保您的新 model 包含在您的init
中:
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
的配置。这里有一个小例子:
// 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()
,这会导致性能下降。
Last updated