Search code examples
reactjsreduxreact-reduxredux-reducers

Redux Action not getting passed to reducer


I am trying to trying to get my textbox to update the word count when the user types something in the box. But the setWordCount action is not getting passed to the reducer. I am at a loss for why this isn't working.

In troubleshooting, I confirmed that the component is pulling the initial word count off state the way it's supposed to. I also confirmed that setWordCount is getting called when the user types something. This should trigger off the action which passes the updated word count to state, but it's not firing. I am not getting any errors in the console and none of my middleware loggers is firing.

This is my component.

import React from 'react';
import { connect } from 'react-redux';
import { setWordCount } from '../../redux/writing/writing.actions';
import { UpdateWordCount, UpdatePercentage } from '../../redux/writing/writing.utils';

import './writing-text-box.styles.scss';

const WritingTextBox = ({wordCount, goal}) => {
    
    var updatedPercentage = UpdatePercentage(wordCount, goal);
    var percent = updatedPercentage + '%';
    
    return (
        <div className='writing-box-container'>
            <textarea className='writing-box' type='text' onChange={
                (e) => {
                  setWordCount(UpdateWordCount(e.target.value));
                }
            }
            />
            <div id='Progress'>
                <div id='Bar' style={{width: percent}}></div>
            </div>
            <p key='writing-box-word-count' className='wordcount' >
                {wordCount} / {goal}</p>
        </div>
    )}

const mapStateToProps = state => ({
    wordCount: state.writing.wordCount, 
    goal: state.writing.goal, 
    percentage: state.writing.percentage
});

const mapDispatchToProps = dispatch => ({
    setWordCount: ({wordCount}) => dispatch(setWordCount(wordCount)),
    // setPercentage: percentage => dispatch(setPercentage(percentage)),
});

export default connect(mapStateToProps, mapDispatchToProps)(WritingTextBox);

This is my actions file, which is nearly copy-pasted from another app that works:

import WritingTypes from "./writing.types";

export const setWordCount = wordCount => ({
    type: WritingTypes.SET_WORD_COUNT,
    payload: wordCount,
});

and my reducer:

import WritingTypes from "./writing.types";

const INITIAL_STATE = {
    wordCount: 0, 
    goal: 124, 
    percentage: 0
}

const writingReducer = (currentState = INITIAL_STATE, action) => {
    switch(action.type) {
        case WritingTypes.SET_WORD_COUNT: 
            return {
                ...currentState,
                wordCount: action.payload
            };
        default:
            return currentState;
    }
}

export default writingReducer;

and my root Reducer:

import { combineReducers } from "redux";

import writingReducer from "./writing/writing.reducer";

const rootReducer = combineReducers ({
    writing: writingReducer
})

export default rootReducer;

Solution

  • You need to be a little more careful with the namings. currently, setWordCount is the name of:

    1. the action creator, which simply creates the action object.

       export const setWordCount = wordCount => ({
       type: WritingTypes.SET_WORD_COUNT,
       payload: wordCount,
       });
      
    2. the prop that dispatches the action.

       setWordCount: ({wordCount}) => dispatch(setWordCount(wordCount)),
      

    in here it should be the second one:

    <textarea className='writing-box' type='text' onChange={
                (e) => {
                  setWordCount(UpdateWordCount(e.target.value));
                }
            }
            />
    

    to make it work, destructure it from props:

    const WritingTextBox = ({wordCount, goal,setWordCount}) => {
    

    now it points to the prop, and works as expected.