Search code examples
reactjsreduxredux-toolkit

Conditionally dispatching actions in Redux Toolkit


I am working on my pomodoro timer using Redux Toolkit.

I am supposed to have three inputs where I can customize the number of minutes for pomodoro period (1), long (2) and short breaks (3).

Therefore, I created <Input/> component and rendered it 3 times in the popup.

//NumberInput.js

import React from 'react';
import styled from "./NumberInput.module.css";

const NumberInput = ({label}) => {
    return (
        <div className={styled.inputContainer}>
            <label htmlFor="">{label}</label>
            <input className={styled.input} type="number" min={0}/>
            <button className={styled.inputBtn} type="button">
                <svg width="14" height="7" viewBox="0 0 14 7" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M1 6L7 2L13 6" stroke="#1E213F" strokeOpacity="0.25" strokeWidth="2"/>
                </svg>
            </button>
            <button className={styled.inputBtn} type="button">
                <svg width="14" height="7" viewBox="0 0 14 7" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M1 1L7 5L13 1" stroke="#1E213F" strokeOpacity="0.25" strokeWidth="2"/>
                </svg>
            </button>
        </div>
    );
};

export default NumberInput;

And I have timerSlice.js where I keep my time data:

import { createSlice } from '@reduxjs/toolkit'

const initialState = {
    pomodoroMinutes: 25,
    shortBreakMinutes: 5,
    longBreakMinutes: 15,
}

const timerSlice = createSlice({
    name: 'timer',
    initialState,
    reducers: {}
})

export default timerSlice.reducer;

The problem is that I can't guess how to dispatch different actions depending on the input user interacts with. For example, if I try to increment/decrement long break minutes I need to dispatch one action to change my longBreakMinutes field in the slice; in case of shortBreakMinutes another action.


Solution

  • You can create an array to distinguish between the inputs and dispatch actions by identifying the input by value to save those changes.

    const ParentComponent = () => {
    const minuteType = ['long', 'short']; 
    
    minuteType.map((type, idx) =>  {
        return <NumberInput type={type} key={idx}/>
    })
    }
    
    const NumberInput = ({label, type}) => {
    const [inputVal, setInputVal] = useState('');
    const dispatch = useDispatch(); 
    
    const saveChanges = () => {
        if (type === 'long') {
            dispatch(saveLongMinutes(inputVal))
        }
        if (type === 'short') { 
            dispatch(saveShortMinutes(inputVal))
        }
    }
    
    return (
     
        {/* Other Content */}
            <input className={styled.input} type="number" min={0} onChange={(event) => setInputVal(event.target.value)}/>
            <button type="button" onclick={saveChanges}>
            Save
        </button>
    );
    

    };

    Redux Store

    const timerSlice = createSlice({
    name: 'timer',
    initialState,
    reducers: {
        saveLongMinutes(state, action) {
            state.longBreakMinutes = action.payload
        }, 
        saveShortMinutes(state, action) {
            state.shortBreakMinutes = action.payload
        }  
    }
    })
    export const { saveLongMinutes, saveShortMinutes } = timerSlice.actions