技巧
- 由于组件内返回 html 结构需要一个根节点,所以很多人选择嵌套一层 view,但是这回影响性能。我们可以定义一个数组,将标签 push 到数组里面然后再返回这个数组,这样组件内就能返回同级的两个标签而不用再嵌套一层 view。
Redux+react-navigation 搭建架子
首先安装一堆第三方库。yarn add react-nativgation react-navigation-redux-helpers redux react-redux redux-devtools redux-thunk
在根路由
AppNavigator.js
li’mina 初始化react-navigation
与redux
的中间件1
2
3
4
5import { createReactNavigationReduxMiddleware } from "react-navigation-redux-helpers"
export const middleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav
)将根导航器组件传递给 reduxifyNavigator 函数,必须在第一步之后执行,返回一个将 navigation state 和 dispath 作为 props 的新组件
1
2
3
4
5
6import { createReduxContainer } from "react-navigation-redux-helpers"
const AppNavigationState = reduxifyNavigator(RootNavigator, "root")
// reduxifyNavigator被弃用
// 改用createReduxContainer
// 必须要写在 createReactNavigationReduxMiddleware 调用之后
const AppNavigationState = createReduxContainer(RootNavigator, "root")设置 state 到 props 的映射关系并导出
1
2
3
4
5
6
7import { connect } from "react-redux"
const mapStateToProps = state => ({
state: state.nav
})
export default connect(mapStateToProps)(AppNavigationState)js 目录下面创建 reducer、action、store 目录
1
2
3
4
5
6
7
8
9
10
11
12
13// action.js
import Types from "../types"
function onThemeChange(theme) {
return {
type: Types.THEME_CHANGE,
theme
}
}
export default {
onThemeChange
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// reducer.js
import { combineReducers } from "redux"
import theme from "./theme"
import { rootCom, RootNavigator } from "../navigator/AppNavigator"
// 1.指定默认state
const navState = RootNavigator.router.getStateForAction(
RootNavigator.router.getActionForPathAndParams(rootCom)
)
// 2. 创建自己的 navigation reducer
const navReducer = (state = navState, action) => {
const nextState = RootNavigator.router.getStateForAction(action, state)
return nextState || state
}
// 3. 合并reducer
const index = combineReducers({
nav: navReducer,
theme: theme
})
export default index上面这个 rootCom 是 AppNavigator.js 根路由里面定义的变量,
export const rootCom = "Init"
变量代表的是初始的路由名。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// reducer theme.js
import Types from "../../action/types"
const defaultState = {
theme: "blue"
}
export default function onAction(state = defaultState, action) {
switch (action.type) {
case Types.THEME_CHANGE:
return {
...state,
theme: action.theme
}
break
default:
return state
break
}
}1
2
3
4
5
6
7
8// store.js
import { applyMiddleware, createStore } from "redux"
import reducers from "../reducer"
import { middleware } from "../navigator/AppNavigator"
const middlewares = [middleware]
export default createStore(reducers, applyMiddleware(...middlewares))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 一堆设置完事了 然后在app.js里面使用 最后由index.js注册根组件
import { Provider } from "react-redux"
import AppNavigator from "./navigator/AppNavigator"
import store from "./store"
import React, { Component } from "react"
type Props = {}
export default class App extends Component<Props> {
render() {
return (
<Provider store={store}>
<AppNavigator />
</Provider>
)
}
}安装 redux-devtools 插件 然后
yarn add redux-devtools-extension
,然后修改下 store.js 文件,这样就能在浏览器利用插件查看 redux 状态。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import { applyMiddleware, createStore, compose } from "redux"
import reducers from "../reducer"
import { middleware } from "../navigator/AppNavigator"
const middlewares = [middleware]
let store
if (
!(
window.__REDUX_DEVTOOLS_EXTENSION__ ||
window.__REDUX_DEVTOOLS_EXTENSION__()
)
) {
store = createStore(reducers, applyMiddleware(...middlewares))
} else {
store = createStore(
reducers,
compose(
applyMiddleware(...middlewares),
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
)
)
}
export default storeHomePage.js 处理安卓物理返回键
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43/*
* @Author: XavierShi
* @Date: 2019-02-11 17:14:20
* @Last Modified by: XavierShi
* @Last Modified time: 2019-02-13 16:49:19
* @Description 底部主路由
*/
import React, { Component } from "react"
import NavigationUtil from "../navigator/NavigationUtil"
import DynamicTabNavigator from "../navigator/DynamicTabNavigator"
import { BackHandler } from "react-native"
import { NavigationActions } from "react-navigation"
import { connect } from "react-redux"
type Props = {}
class HomePage extends Component<Props> {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress)
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress)
}
onBackPress = () => {
const { dispatch, nav } = this.props
if (nav.index === 0) {
return false
}
dispatch(NavigationActions.back())
return true
}
render() {
NavigationUtil.navigation = this.props.navigation
return <DynamicTabNavigator />
}
}
const mapStateToProps = state => ({
nav: state.nav
})
export default connect(mapStateToProps)(HomePage)