0

action;

export const ON_MESSAGE = 'ON_MESSAGE';

export const sendMessage = (text, sender = 'user') => ({
  type: ON_MESSAGE,
  payload: { text, sender },
});

reducer:

import { ON_MESSAGE } from 'Redux/actions/Chat_action';
import { act } from 'react-dom/test-utils';

const initalState = [{ text: [] }];

const messageReducer = (state = initalState, action) => {
  switch (action.type) {
    case ON_MESSAGE:
      return [...state, action.payload];
    default:
      return state;
  }
};

export default messageReducer;

combine reducer:

import Chat from 'Redux/reducers/Chat_reducer';

export default combineReducers({
  Chat,
});

store:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer';

export default function configureStore(initialState) {
  return createStore(rootReducer, applyMiddleware(thunk));
}

and code:

const Chat = props => {
  const dispatch = useDispatch();
  const messages = useSelector(state => state.Chat);
  const [text, setText] = React.useState('');
  console.log(messages);
  return (
    <Styled.ChatBox>
      <Styled.ChatHeader>
        <p>Chat Bot</p>
        <div>
          <FontAwesomeIcon icon={faAngleDown} size="1x" color="white" />
          <FontAwesomeIcon icon={faTimes} size="1x" color="white" />
        </div>
      </Styled.ChatHeader>
      <Styled.ChatLog>
        {messages.map(message => (
          <Styled.ChatMessage>{message.text}</Styled.ChatMessage>
        ))}
      </Styled.ChatLog>
      <Styled.ChatInput>
        <textarea
          value={text}
          onChange={e => setText(e.target.value)}
          placeholder="Digite aqui sua mensagem"
        />
        <button onClick={() => dispatch(sendMessage({ text }))}>
          <FontAwesomeIcon icon={faPaperPlane} size="lg" color="black" />
        </button>
      </Styled.ChatInput>
    </Styled.ChatBox>
  );
};

basically my initial message appears normally in my chat body but when I type a message and use the dispatch I get the following errors:

Uncaught Error: Objects are not valid as a React child (found: object with keys {text}).

and

The above error occurred in the component:

the problem is here:

  <Styled.ChatLog>
    {messages.map(message => (
      <Styled.ChatMessage>{message.text}</Styled.ChatMessage>
    ))}
  </Styled.ChatLog>
8
  • In your reducer, can you spread the action.payload too and see if that helps? [...state, ...action.payload] Commented Jan 31, 2020 at 13:38
  • is this: {text: Array(1)} 1: {text: {…}, sender: "user"} ? Commented Jan 31, 2020 at 13:39
  • I think the problem is with your reducer case ON_MESSAGE, I think something with the way you add the action.payload is not right, that's why I suggested it. Does it help or you still get the same error? Commented Jan 31, 2020 at 13:42
  • yeah now i got this: action.payload is not iterable Commented Jan 31, 2020 at 13:50
  • but why would my problem be my payload? I can see the initial message in my chat I just cannot see when rendering new message components Commented Jan 31, 2020 at 13:51

4 Answers 4

1

The problem is that your action is expecting individual parameters but you are passing a single object

export const sendMessage = (text, sender = 'user') => ({
  type: ON_MESSAGE,
  payload: { text, sender },
});
dispatch(sendMessage({ text }))

Because of this, your reducer shape is actually [{ text: { text: "..." } }] instead of [{ text: "..." }]

This means that message.text is actually an object { text: '...' }, causing the error:

<Styled.ChatMessage>{message.text}</Styled.ChatMessage>

To fix this, you need to pass values as individual parameters to your action, like so:

dispatch(sendMessage(text))
Sign up to request clarification or add additional context in comments.

1 Comment

Oops could you help me with one more thing? I'm a little confused as to how I could send a set message that was a user who sent it in relation to the reducer I will probably have to make a middlware to return if it is a bot or not with the value
0

maybe you can change your initalState to an object spread the action payload inside the text array like this:

const initalState = { text: [] };

return [...state, text: [...action.payload]];

1 Comment

i try this but got error: Parsing error: Unexpected token
0

Most probably its an issue with the reducer when you are updating the state..Please check the value of state and action.payload.text.Also, try to use the initial state as an object instead an Array so that accessing keys in easy. In your case keys in the state might be sender and text.

var initialState = { text: ["msg1"] };

action.payload= {text:"msg2",sender:"user"}; Make sure that action that payload.text is like above value.

And finally, merge them like mentioned below. This will add new msg to the array of texts instead of overriding msg every time.

var newState = {"text":Object.assign({},state.text,action.payload)};

You will also need to update the array.map in your jsx.

7 Comments

but in my payload I have an attribute where I indicate if it is a bot or user msg.
i have text, and sender.
I didn't understand how I'm going to apply the new State could you help me with this?
Sure...I guess you need to capture user for each msg. So update your data structure as follows: var initialState={ logs: [{text:"msg1",sender:"user1"}] }; var action.payload={text:"msg2",sender:"user2"} ** **var newState={"logs": [...state.logs,action]}; Put console logs and see the action. payload and initial state should have same structure as above
update code: var initialState={ logs: [{text:"msg1",sender:"user1"}] }; action.payload={text:"msg2",sender:"user2"} var newState={"logs": [...state.logs,action.payload]}
|
0

You are trying to render array as react child (message.text is an array):

  <Styled.ChatLog>
    {messages.map(message => (
      <Styled.ChatMessage>{message.text}</Styled.ChatMessage>
    ))}

Try this:

  <Styled.ChatLog>
    {messages.map(message => (
      <Styled.ChatMessage>{message.text.join()}</Styled.ChatMessage>
    ))}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.