React-Redux: arguments not being dispatched

Hi All :slight_smile:

I have been working through a tutorial article written by Emannuel Ohans on FCC, where we create a skype clone app.

I’m stuck on a section where I’m trying to create a feature that allows me to type text into the chat and update the redux store with the new information, followed by an update on the chat window showing the submitted text as a sent message

For some reason, when I run my code and investigate using console.log, the arguments I put into my dispatch for the

message.js

messages function come out as undefined, NaN and null… could someone please point me in the right direction for debugging?

It’s complicated to show all the different folders here but I hope this is clear enough.

// ...\src\actions\index.js

import { 
    SET_ACTIVE_USER_ID, 
    SET_TYPING_VALUE,
    SEND_MESSAGE
} from "../constants/action-types";

export const setActiveUserId = id => ({
    type: SET_ACTIVE_USER_ID,
    payload: id
});

export const setTypeValue = inputValue => ({
    type: SET_TYPING_VALUE,
    payload: inputValue
});

export const sendMessage = (message, userId) => ({
    type: SEND_MESSAGE,
    payload: {
        message: message,
        userId: userId
    }
});

// …\src\components\ChatWindow.js

import "./ChatWindow.css";
import React from "react";
import store from "../store";
import Header from "../components/Header";
import Chats from "../components/Chats";
import MessageInput from "../containers/MessageInput";
import _ from "lodash";


const ChatWindow = ({ activeUserId }) => {
    const state = store.getState();
    const activeUser = state.contacts[activeUserId];
    const activeMsgs = state.messages[activeUserId];
    const { typing } = state;

    return (
        <div className="ChatWindow">
            <Header user={activeUser} />
            <Chats messages={_.values(activeMsgs)}/>
            <MessageInput value={typing}/>
        </div>
    );
};



export default ChatWindow;
// …\src\components\chats.js


import "./Chats.css";
import React, { Component } from "react";

const Chat = ({ message }) => {
    const { text, is_user_msg } = message;
    return (
        <span className={`Chat ${is_user_msg ? "is-user-msg" : ""}`}>{text}</span>
    );
};

class Chats extends Component {
    render() {
        return (
            <div className="Chats">
                {this.props.messages.map(message => (
                    <Chat message={message} key={message.number} />
                ))}
            </div>
        );
    }
}

export default Chats;

// …\src\containers\MessageInput.js

import "./MessageInput.css";
import React from "react";
import store from "../store";
import { sendMessage, setTypeValue } from "../actions";
import { state } from "../static-data";

//supporting functions



// main export
const MessageInput = ({ value }) => {

    const handleSubmit = e => {
        e.preventDefault();
        const { typing, activeUserId } = state;
        console.log(typing, activeUserId);
        store.dispatch(sendMessage(typing, activeUserId));
    };
    
    const handleChange = e => {
        store.dispatch(setTypeValue(e.target.value));
    };

    return (
        <form className="Message" onSubmit={handleSubmit}>
            <input
                className="Message__input"
                onChange={handleChange}
                value={value}
                placeholder="write a message" 
            />
        </form>
    );
};

export default MessageInput;

// …\reducer\index.js.js


import user from "./user";
import contacts from "./contacts";
import activeUserId from "./activeUserId";
import messages from "./messages";
import typing from "./typing";
import { combineReducers } from "redux";


export default combineReducers({
    user,
    messages,
    typing,
    contacts,
    activeUserId
})

// …\reducer\messages.js

import { getMessages } from "../static-data";
import { SEND_MESSAGE } from "../constants/action-types";
import _ from "lodash";

export default function messages(state = getMessages(10), action) {
    switch (action.type) {
        case SEND_MESSAGE:
            const message = action.payload.message;
            const userId = action.payload.userId;
            const allUserMsgs = state[userId];
            const number = 10;
            console.log(message, userId, allUserMsgs, number, "test");
            return {
                ...state,
                [userId]: {
                    ...allUserMsgs,
                    [number]: {
                        number,
                        text: message,
                        is_user_msg: true
                    }
                }
            }
        default:
            return state;
    }
}

// …\reducer\typing.js

import { SET_TYPING_VALUE } from "../constants/action-types";

export default function typing(state = "", action) {
    switch(action.type) {
        case SET_TYPING_VALUE:
            return action.payload;
        default:
            return state;
    }
}

// …\store\index.js


import {createStore} from "redux";
import reducer from "../reducer/index";

const store = createStore(reducer);

export default store;

It’s kind of hard to see.

I would recommend logging out the values at every step of the chain. Start where you know what it is and it works properly. Then step on through, every step of the way, even in the action creator and the reducer. Log it out and work your way until you find where it stops doing what it is supposed to do - then you’ve found your bug (most likely).

Try that first. If that doesn’t work, do you have a repo for this?

1 Like

Thank you!

I went over the logs again and finally found the issue.

In the end, it was because I had connected a component directly to the redux store instead of going through getState(), so it wasn’t drawing information from the up to date store.

the culprit file is below for anyone interested.

// …\src\containers\MessageInput.js

import "./MessageInput.css";
import React from "react";
import store from "../store";
import { sendMessage, setTypeValue } from "../actions";

// #######
import { state } from "../static-data"; // this is the culprit!!
// #######

//supporting functions



// main export
const MessageInput = ({ value }) => {
// ######
    // should have been state = store.getState();
// ######
    const handleSubmit = e => {
        e.preventDefault();
        const { typing, activeUserId } = state; 
        console.log(typing, activeUserId);
        store.dispatch(sendMessage(typing, activeUserId));
    };
    
    const handleChange = e => {
        store.dispatch(setTypeValue(e.target.value));
    };

    return (
        <form className="Message" onSubmit={handleSubmit}>
            <input
                className="Message__input"
                onChange={handleChange}
                value={value}
                placeholder="write a message" 
            />
        </form>
    );
};

export default MessageInput;