user12356906
user12356906

Reputation:

React js and Redux : Objects are not valid as a React child

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>

Upvotes: 0

Views: 809

Answers (4)

Craig Ayre
Craig Ayre

Reputation: 1173

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))

Upvotes: 1

Kaca992
Kaca992

Reputation: 2267

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>
    ))}

Upvotes: 0

a.developer
a.developer

Reputation: 59

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.

Upvotes: 0

ThanosK
ThanosK

Reputation: 51

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]];

Upvotes: 0

Related Questions