Search code examples
javascriptreact-nativereduxreact-reduxredux-thunk

Calling an action triggers multiple reducers?


I just send one action in LoginAction, but it triggers three reducers. I don't know why...

Version:

"react": "16.9.0",
"react-native": "0.61.2",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",

Here is my setting.

App.js:

import React from 'react';
import ReduxThunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { compose, createStore, applyMiddleware } from 'redux';
// import { persistStore } from 'redux-persist';
// import { PersistGate } from 'redux-persist/integration/react';
import reducers from './src/reducers';
import AppContainer from './src/navigator' // It is my react-navigation route

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const App: () => React$Node = () => {
  if (!__DEV__) {
    console.log = () => {};
  }

  const store = createStore(reducers, {}, composeEnhancers(applyMiddleware(ReduxThunk)));

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

export default App;

My LoginAction.js:

export const testAction = () => {
  return (dispatch) => {
    dispatch( { type: 'TEST_ACTION' });
  }
}

My reducer setting: reducers/index.js

import { combineReducers } from 'redux';
import LoginReducer from './LoginReducer';
import StoreReducer from './StoreReducer';
import ReservationReducer from './ReservationReducer';

export default combineReducers({
  LoginRedux: LoginReducer,
  StoreRedux: StoreReducer,
  ReservationRedux: ReservationReducer
});

My LoginReducer.js: (StoreReducer and ReservationReducer are the same as LoginReducer)

const INITIAL_STATE = {
  ...my state arguments
};

export default (state = INITIAL_STATE, action) => {

  // Here is my issue !
  // StoreReducer is 'StoreReducer reducer =>', action
  // ReservationReducer is 'ReservationReducer reducer =>', action
  console.log('Login reducer =>', action);  

  switch (action.type) {
    case 'SOME_ACTION': 
      return {
        // state setting from action
      };
    default:
      return state;
    }
};

Call the action component is LoginScreen.js:

import React, { Component } from 'react';
import { 
  // some view
} from 'react-native';
import { connect } from 'react-redux';
import { login, closeLoadingCheckModal, testAction } from '../actions';

class LoginScreen extends Component {
  constructor(props) {
    super(props);

    this.state = { 
      // some states
    };
  }

  render() {
    return (
      <View>
        <TouchableOpacity onPress={() => { this.props.testAction() }>
          <Text>Press Test Action</Text>
        </TouchableOpacity>
      </View>
    );
  }
const mapStateToProps = (state) => {
  const { ...some store value  } = state.LoginRedux;

  return { ...some store value  };
};

}

export default connect(mapStateToProps, { login, closeLoadingCheckModal, testAction })(LoginScreen);

When I trigger the action, all of the reducers will be triggered.

It should only console log Login reducer =>

Anyone knows what is my problem?

enter image description here


Solution

  • If you're using combineReducers, all your slice reducers will run for every dispatched action. It's a question of whether a given reducer actually calculates new state or not.

    See the Redux FAQ entry on "is there a 1:1 mapping between reducers and actions?" for more details.