user7417739
user7417739

Reputation:

Modify one state property in two Reducers in Redux

I have a small problem with Redux in my state I need to be able to modify my counter property in two Reducers as it's value update to both reducers (INCREMENT, DECREMENT) sorry am new to Redux and try to understand this concept.

Counter Component


        return(
            <>
                <div className="flex justify-center">
                    <div className='font-bold text-4xl text-blue-600 bg-gray-300 p-6 m-3 rounded-full'>The Result :
                        {this.props.counter}
                    </div>
                </div>
                <section className='flex p-5 m-3 justify-center'>
                    <button onClick={this.props.increment} className={`bg-green-400 ${btnDefault}`} >Increment</button>
                    <button onClick={() => this.props.decrement(this.props.counter)} className={`bg-red-400 ${btnDefault}`}>Decrement</button>
                </section>
            </>
        )
    }
}


const mapStateToProps = state => {
    return {
        counter: state.incReducer.counter,
    }
};
const mapDispatchToProps = dispatch => {
    return {
        increment: () => dispatch(counterAction('INCREMENT')),
        decrement: (counter) => dispatch(counterAction('DECREMENT',counter))
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(Counter)

Increment Reducer

const initialState = {
    counter: 0,
};

const reducer = (state = initialState, action) => action.type === actionType.INCREMENT ?
        {
        ...state,
        counter: state.counter + 1
        }
    : state;


export default reducer;

Decrement Reducer

const initState = {

};

const reducer = (state = initState, action) => action.type === actionType.DECREMENT ?
    {
        ...state,
        counter: action.counter - 1
    }
    : state;

export default reducer;

Index.js

const reducer = combineReducers({
    incReducer,
    decReducer
});

const store = createStore(reducer);

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

Upvotes: 2

Views: 1157

Answers (1)

dave
dave

Reputation: 64687

You're just approaching it from the wrong angle, you should never have the same variable being modified in two reducers, you instead want to have a single counterReducer that handles all actions that modify the counter:

const initialState = {
    counter: 0,
};

const reducer = (state = initialState, action) => {
    switch(action.type) {
        case actionType.INCREMENT:
            return {
                ...state,
                counter: state.counter + 1
            };
            break;
        case actionType.DECREMENT:
            return {
                ...state,
                counter: state.counter - 1
            }
            break;
        default:
            return state;
    }
}

export default reducer;

Splitting into multiple reducers is a way to keep your code organized, but you'd never have two reducers that could each modify the same thing. Each reducer should instead handle a certain "section" of your overall state, e.g.

const totalState = {
    activeUser: { /* username, email, phone, etc */ },
    friends: [],
    subscriptions: [],
    history: [],
    // etc.
}

you might then have an activeUserReducer, friendsReducer, subscriptonsReducer, historyReducer, etc. And each one would handle that portion of the state, but would never reach into another reducers state.

If you need to modify two different properties with a single action, you would just do:

const mapDispatchToProps = dispatch => {
    return {
        increment: () => {
            dispatch(counterAction('INCREMENT'));
            dispatch(someOtherAction());
        }
    };
};

Upvotes: 1

Related Questions