【问题标题】:Is there a way to call dispatch "statically" outside a connected component with react-redux?有没有办法在使用 react-redux 的连接组件外部“静态”调用调度?
【发布时间】:2017-04-20 22:22:21
【问题描述】:

考虑以下代码:

/**
 * 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

我在“菜单”中的所有场景,包括它都是连接组件

   const mapStateToProps = (state) => {

    return {
        ...state.First
    };

};

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

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

那么,问题来了:有没有办法在连接组件之外调用调度,或者是连接“MyApp”组件的最佳方式?

【问题讨论】:

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


    【解决方案1】:

    几件事。

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

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

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

    【讨论】:

    • 嘿markerikson...由于评论的限制,我发布了我的考虑来回答我的问题。谢谢!
    【解决方案2】:

    好方法!根据您的建议,我查看了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;
    

    【讨论】:

      猜你喜欢
      • 2017-09-26
      • 2019-10-23
      • 2017-08-28
      • 2013-04-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多