RN开发GitHub

技巧

  1. 由于组件内返回 html 结构需要一个根节点,所以很多人选择嵌套一层 view,但是这回影响性能。我们可以定义一个数组,将标签 push 到数组里面然后再返回这个数组,这样组件内就能返回同级的两个标签而不用再嵌套一层 view。

Redux+react-navigation 搭建架子

首先安装一堆第三方库。
yarn add react-nativgation react-navigation-redux-helpers redux react-redux redux-devtools redux-thunk

  1. 在根路由AppNavigator.jsli’mina 初始化 react-navigationredux的中间件

    1
    2
    3
    4
    5
    import { createReactNavigationReduxMiddleware } from "react-navigation-redux-helpers"
    export const middleware = createReactNavigationReduxMiddleware(
    "root",
    state => state.nav
    )
  2. 将根导航器组件传递给 reduxifyNavigator 函数,必须在第一步之后执行,返回一个将 navigation state 和 dispath 作为 props 的新组件

    1
    2
    3
    4
    5
    6
    import { createReduxContainer } from "react-navigation-redux-helpers"
    const AppNavigationState = reduxifyNavigator(RootNavigator, "root")
    // reduxifyNavigator被弃用
    // 改用createReduxContainer
    // 必须要写在 createReactNavigationReduxMiddleware 调用之后
    const AppNavigationState = createReduxContainer(RootNavigator, "root")
  3. 设置 state 到 props 的映射关系并导出

    1
    2
    3
    4
    5
    6
    7
    import { connect } from "react-redux"

    const mapStateToProps = state => ({
    state: state.nav
    })

    export default connect(mapStateToProps)(AppNavigationState)
  4. 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>
    )
    }
    }
  5. 安装 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
    24
    import { 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 store
  6. HomePage.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)
Author: XavierShi
Link: https://blog.xaviershi.com/2019/01/26/RN开发GitHub/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.