尝试将Redux集成到React Navigation中

时间:2018-02-07 10:40:05

标签: react-native redux react-redux react-navigation

我正在尝试将Redux集成到使用React Navigation的现有React Native应用程序中。

package.json 文件中的依赖关系是:

"react": "^16.0.0",
"react-native": "^0.51.0",
"react-native-smart-splash-screen": "^2.3.5",
"react-navigation": "^1.0.0-rc.2",
"react-navigation-redux-helpers": "^1.0.0",

我的代码是:

./ App.js

import React, { Component } from "react"
import { AppRegistry, StyleSheet, View } from "react-native"
import { Provider } from "react-redux"
import { createStore } from "redux"
import SplashScreen from "react-native-smart-splash-screen"

import AppReducer from "./reducers/AppReducer"
import AppWithNavigationState from "./navigators/AppNavigator"


class App extends Component {

    store = createStore(AppReducer);

    componentWillMount() {
        SplashScreen.close({
            animationType: SplashScreen.animationType.scale,
            duration: 850,
            delay: 500,
        });
    }

    render() {
        return (
            <Provider store={store}>
                <AppWithNavigationState />
            </Provider>
        )
    }
}

AppRegistry.registerComponent("App", () => App)

export default App

./导航/ AppNavigator.js

import { addNavigationHelpers, StackNavigator } from "react-navigation"
import { connect } from "react-redux"

import StackLoading from "../screens/app/StackLoading"
import StackAuth from "../screens/auth/StackAuth"

export const AppNavigator = StackNavigator({
    Login: { screen: StackAuth },
    Main: { screen: StackLoading },
},
{
    headerMode: 'screen',
    header: null,
    title: 'MyApp',
    initialRouteName: 'Login',
})

const AppWithNavigationState = ({ dispatch, nav }) => (
    <AppNavigator
        navigation={addNavigationHelpers({ dispatch, state: nav })}
    />
);

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

export default connect(mapStateToProps)(AppWithNavigationState)

./减速器/ AppReducer.js

import { combineReducers } from 'redux';
import NavReducer from './NavReducer';

const AppReducer = combineReducers({
    nav: NavReducer,
});

export default AppReducer;

./减速器/ AppReducer.js

import { combineReducers } from 'redux';
import { NavigationActions } from 'react-navigation';

import { AppNavigator } from '../navigators/AppNavigator';

const router = AppNavigator.router;
const mainNavAction = AppNavigator.router.getActionForPathAndParams('Main')
const mainNavState = AppNavigator.router.getStateForAction(mainNavAction);
const loginNavAction = AppNavigator.router.getActionForPathAndParams('Login')
const initialNavState = AppNavigator.router.getStateForAction(loginNavAction, mainNavState)

function nav(state = initialNavState, action) {
    let nextState;
    switch (action.type) {
        case 'Login':
            nextState = AppNavigator.router.getStateForAction(
                NavigationActions.back(),
                state
            );
            break;

        case 'Logout':
            nextState = AppNavigator.router.getStateForAction(
                NavigationActions.navigate({ routeName: 'Login' }),
                state
            );
            break;

        default:
            nextState = AppNavigator.router.getStateForAction(action, state);
            break;
    }

    // Simply return the original `state` if `nextState` is null or undefined.
    return nextState || state;
}

const initialAuthState = { isLoggedIn: false };

function auth(state = initialAuthState, action) {
    switch (action.type) {
        case 'Login':
            return { ...state, isLoggedIn: true };
        case 'Logout':
            return { ...state, isLoggedIn: false };
        default:
            return state;
    }
}

const AppReducer = combineReducers({
  nav,
  auth,
});

export default AppReducer;

我在尽可能多的指南中使用了各种方法。我继续犯的错误是:

  

ReactNativeJS:undefined不是对象(评估   'state.routes [childIndex]')

     

ReactNativeJS:模块AppRegistry不是   注册的可调用模块(调用runApplication)

请帮帮我:\

2 个答案:

答案 0 :(得分:0)

PrimaryNavigator是我的顶级导航器。

我正在使用一些辅助函数来禁止多次将相同的组件推送到堆栈,这是反应导航中的常见问题。

我的助手功能分别;

function hasProp(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    }

    // Gets the current route name
    function getCurrentRouteName(nav) {
        if (!hasProp(nav, 'index') || !hasProp(nav, 'routes')) return nav.routeName;
        return getCurrentRouteName(nav.routes[nav.index]);
    }

    function getActionRouteName(action) {
        const hasNestedAction = Boolean(
            hasProp(action, 'action') && hasProp(action, 'type') && typeof action.action !== 'undefined',
        );

        const nestedActionWillNavigate = Boolean(hasNestedAction && action.action.type === NavigationActions.NAVIGATE);

        if (hasNestedAction && nestedActionWillNavigate) {
            return getActionRouteName(action.action);
        }

        return action.routeName;
    }

然后设置导航减速器:

const initialState = PrimaryNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: 'StartingScreen' })
    );

    const navReducer = (state = initialState, action) => {
        const { type } = action;

        if (type === NavigationActions.NAVIGATE) {
            // Return current state if no routes have changed
            if (getActionRouteName(action) === getCurrentRouteName(state)) {
                return state;
            }
        }

        // Else return new navigation state or the current state
        return PrimaryNavigator.router.getStateForAction(action, state) || state;
    }

最后,您可以在combineReducers函数中组合navReducer。

如果我的回答对您的案件没有帮助,请告诉我

答案 1 :(得分:0)

AppRegistry.registerComponent(“App”,()=&gt; App)应该在index.ios.js或index.android.js中发生

你的index.ios.js文件看起来应该是

import App from './src/App';
import { AppRegistry } from 'react-native';

AppRegistry.registerComponent('your_app_name', () => App);