有没有办法调度发送"静态"使用react-redux在连接组件外面?

时间:2017-04-20 22:22:21

标签: firebase react-native redux firebase-authentication react-redux

请考虑以下代码:

/**
 * OTHER IMPORTS...
 */
import React, {Component} from 'react';
import {connect, Provider} from 'react-redux';
import {createStore, applyMiddleware, combineReducers, compose} from 'redux';
import firebase from 'firebase';

/**
 * Connected Router - Flux Router with Connected Redux
 */
const ReduxRouter = connect()(Router);

class MyApp extends Component {

    // Many Methods

    /**
     *
     */
    componentWillMount () {

        firebase.initializeApp({});

        firebase.auth().onAuthStateChanged(this.onAuthStateChangedCallback.bind(this));

        if (!this.reducers) {

            this.reducers = combineReducers({
                ... // Many Reducers for other Scenes
            });

        }

        if (!this.store) {

            this.store = compose(applyMiddleware(ReduxThunk))(createStore)(this.reducers);

        }

    }

    /**
     *
     */
    onAuthStateChangedCallback (user) {

        if (user) {

            /*

            // TODO DISPATCH <------ Here is my problem

            dispatch({
                type: 'LOGGED',
                payload: user
            });

            */

            Actions.First();

        } else {

            this.setState({
                isLoading: false,
                loggedIn: false
            });

            Actions.LogIn();

        }

    }

    render () {

        return (
            <Provider store={this.store}>
                <ReduxRouter sceneStyle={{paddingTop: 0, backgroundColor: '#FFFFFF'}}>
                    <Scene key="Menu" component={MenuScene} open={false} type={ActionConst.REPLACE} passProps>
                        {/* MANY OTHERS SCENES */}
                        <Scene key="First" title="First" type={ActionConst.REPLACE} component={FirstScene} passProps />
                        <Scene key="LogIn" title="LogIn" type={ActionConst.REPLACE} component={LogInScene} passProps />
                    </Scene>
                </ReduxRouter>
            </Provider>
        );

    }

}

export default MyApp

我的所有场景&#34;菜单&#34;,包括它是连接组件

   const mapStateToProps = (state) => {

    return {
        ...state.First
    };

};

export default connect(mapStateToProps, {
   ... // Actions
})(First);

我决定在主要组件中设置firebase auth回调。有一种情况我需要调度一些动作,所以我的所有场景都会读取在这种情况下应该调度的数据。

所以,问题是:有没有办法在连接组件外调用调度,或者是连接&#34; MyApp&#34;成分

2 个答案:

答案 0 :(得分:2)

一些事情。

首先,理想情况下,您应该在组件层次结构中创建商店 ,通常是在应用程序入口点。例如:

// index.js

const store = createStore(rootReducer);

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById("root")
);

其次,您可以通过组件层次结构将dispatch作为prop传递,或者只是连接其他组件。基本上,任何想要与商店交互的组件都应使用connect()。如果您未将mapDispatchToProps函数传入connect,您的组件将自动获得props.dispatch

答案 1 :(得分:1)

很棒的方法!除了你的建议,我查看了docs,最后得到了index.js的这个结构。我认为代码本身解释了结构。再次感谢您的帮助!

/**
* Modules dependencies
*/
import React, {Component} from 'react';
import {AppState} from 'react-native';
import {connect, Provider} from 'react-redux';
import {createStore, applyMiddleware, combineReducers, compose} from 'redux';
import ReduxThunk from 'redux-thunk';
import {Scene, Router, ActionConst, Actions} from 'react-native-router-flux';
import firebase from 'firebase';

/**
 * Internal dependencies
 */
import {default as MyScene1Reducer} from './MyScene1/reducer';
import {default as MyScene2Reducer} from './MyScene2/reducer';
import {default as MyScene3Reducer} from './MyScene3/reducer';

import {default as MyScene1} from './MyScene1';
import {default as MyScene2} from './MyScene2';
import {default as MyScene3} from './MyScene3';

/**
 * Firebase
 */
firebase.initializeApp({
    apiKey: '',
    authDomain: '',
    databaseURL: '',
    storageBucket: '',
    messagingSenderId: ''
});

/**
 * Scenes
 */
const Scenes = Actions.create(
    <Scene key="Menu" component={MenuScene} open={false} type={ActionConst.REPLACE} passProps>
        <Scene key="MyScene1" title="MyScene1" type={ActionConst.REPLACE} component={MyScene1} passProps />
        <Scene key="MyScene2" title="MyScene2" type={ActionConst.REPLACE} component={MyScene2} passProps />
        <Scene key="MyScene3" title="MyScene3" type={ActionConst.REPLACE} component={MyScene3} passProps />
    </Scene>
 );

const ReduxRouter = connect()(Router);

const Reducers = combineReducers({
    MyScene1: MyScene1Reducer,
    MyScene2: MyScene2Reducer,
    MyScene3: MyScene3Reducer
});

const Store = compose(applyMiddleware(ReduxThunk))(createStore)(Reducers);

/**
 * The Main Component - View
 */
class MyApp extends Component {

    /**
     *
     */
    constructor(props) {

        super(props);

        this.state = {

        };

    }

    /**
     *
     */
    componentWillMount () {

        firebase.auth().onAuthStateChanged(this.onAuthStateChangedCallback.bind(this));

    }

    /**
     *
     */
    componentDidMount () {

        AppState.addEventListener('change', this.onAppStateChangeCallback);

    }

    /**
     *
     */
    componentWillUnmount() {

        AppState.removeEventListener('change', this.onAppStateChangeCallback);

    }

    /**
     *
     */
    onAppStateChangeCallback = (nextAppState) => {

        console.log(nextAppState);

    }

    /**
     * 
     */
    onAuthStateChangedCallback (user) {

        if (user) {

            console.log(this.props.dispatch); <---- Exists!

            Actions.MyScene2();

        } else {

            Actions.MyScene3();

        }

    }

    /**
     *
     */
    render () {

        return (
            <ReduxRouter scenes={Scenes} sceneStyle={{paddingTop: 0, backgroundColor: '#FFFFFF'}} />
        );

    }

}

/**
* The Main Component - Provider / Store
*/
const MyAppStore = () => {

    const MyAppConnected = connect()(MyApp);

    return (
        <Provider store={Store}>
            <MyAppConnected />
        </Provider>
    );

};

export default MyAppStore;