Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Posted data cannot be displayed with reactjs

Tags:

reactjs

The code below works fine by displaying users info in a popup box. Now I want to send message to each user to a nodejs server. The message got posted as I can see it in the nodejs server end console.

In reactjs console, as per code below

const addMessage = data => {
    console.log(data);
    this.setState({messages: [...this.state.messages, data]});
};

am seeing the message sent in the console as per

{author: "Nancy ", message: "first message"}

Here is my issue:

1.) The message is not displayed within the render method despite the fact that I have set it to this.props.messages.. 2.) When I typed on the input form am seeing error warning in the console as per below

Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. in input (created by OpenedUser)

Below is how am posting and retrieving it from nodejs server

componentDidMount(){
    this.socket = io('http://localhost:8080');
    this.socket.on('response message', function(data){
        addMessage(data);
    });
    const addMessage = data => {
        console.log(data);
        this.setState({messages: [...this.state.messages, data]});
    };
} // close component didmount

sendMessage = ev => {
    ev.preventDefault();
    this.socket.emit('chatMessage', {
        author: this.state.username,
        message: this.state.message
    })
    this.setState({message: ''});
}

Here is the full working code so far

//npm install --save socket.io
//npm install --save socket.io-client


import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import { Link } from 'react-router-dom';
import axios from 'axios';
import io from "socket.io-client";


class User extends React.Component {
  open = () => this.props.open(this.props.data.id, this.props.data.name);
  render() {
    return (
      <React.Fragment>
        <div key={this.props.data.id}>
          <button
            onClick={() => this.open(this.props.data.id, this.props.data.name)}
          >
            {this.props.data.name}
          </button>
        </div>
      </React.Fragment>
    );
  }
}

class OpenedUser extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            hidden: false
        };
    }
    componentDidMount(){
        this.socket = io('http://localhost:8080');
        this.socket.on('response message', function(data){
            addMessage(data);
        });
        const addMessage = data => {
            console.log(data);
            this.setState({messages: [...this.state.messages, data]});
        };
    } // close component didmount


    sendMessage = ev => {
        ev.preventDefault();
        this.socket.emit('chatMessage', {
            author: this.state.username,
            message: this.state.message
         })
         this.setState({message: ''});
    }

    toggleHidden = () => this.setState(prevState => ({ hidden: !prevState.hidden }));

    close = () => this.props.close(this.props.data.id);

    render() {
        return (
            <div key={this.props.data.id} style={{ display: "inline-block" }}>
                <div className="msg_head">
                    <button onClick={this.close}>close</button>
                    <div>user {this.props.data.id}</div>
                    <div>name {this.props.data.name}</div>
                    {this.state.hidden ? null : (
                            <div className="msg_wrap">
                            <div className="msg_body">Message will appear here</div>
                            <b> {" "} Display Chat Message below...{" "}</b>



<div>
                                    {this.props.messages.map(message => {
                                        return (
                                            <div>{message.author}: {message.message}</div>
                                        )
                                    })}
                                </div>

 <div>
                                <input type="text" placeholder="Username" value={this.state.username} onChange={ev => this.setState({username: ev.target.value})}/>
                                <br/>
                                <input type="text" placeholder="Message" value={this.state.message} onChange={ev => this.setState({message: ev.target.value})}/>
                                <br/>
                                <button onClick={this.sendMessage} className="btn btn-primary">Send message</button>
                            </div>



            </div>
          )}
        </div>
      </div>
    );
  }
}
class App extends React.Component {
  constructor() {
    super();

    this.state = {
loading_image: false,
      shown: true,
      activeIds: [],
 username: '',
 message: '',
 messages: [],



      data: [
        { id: 1, name: "user 1" },
        { id: 2, name: "user 2" },
        { id: 3, name: "user 3" },
        { id: 4, name: "user 4" },
        { id: 5, name: "user 5" }
      ]
    };
  }

  toggle() {
    this.setState({
      shown: !this.state.shown
    });
  }


  open = (id, name) => {
    alert(id);
    alert(name);

    //start axios api call

    const user_data = {
      uid: "id",
      uname: "name"
    };



    this.setState(prevState => ({
      activeIds: prevState.activeIds.find(user => user === id)
        ? prevState.activeIds
        : [...prevState.activeIds, id]
    }));
  };

  close = id => {
    this.setState(prevState => ({
      activeIds: prevState.activeIds.filter(user => user !== id)
    }));
  };

  renderUser = id => {
    const user = this.state.data.find(user => user.id === id);
    if (!user) {
      return null;
    }
    return (
      <OpenedUser
        chatData={this.state.chatData}   messages={this.state.messages}
        key={user.id}
        data={user}
        close={this.close}
      />
    );
  };

  renderActiveUser = () => {
    return (
      <div style={{ position: "fixed", bottom: 0, right: 0 }}>
        {this.state.activeIds.map(id => this.renderUser(id))}
      </div>
    );
  };

  render() {


    return (
      <div>
        {this.state.data.map(person => (

          <User key={person.id} data={person} open={this.open} />

        ))}
        {this.state.activeIds.length !== 0 && this.renderActiveUser()}
      </div>
    );
  }
}
like image 401
jmarkatti Avatar asked Dec 06 '25 05:12

jmarkatti


1 Answers

Within OpenedUser.sendMessage, you have following code to associate input values to this.state.username/message respectively.

// Reformatted to remove scrollbars
<input type="text" placeholder="Username" 
       value={this.state.username} 
       onChange={ev => this.setState({username: ev.target.value})}/>
<br />
<input type="text" placeholder="Message" 
       value={this.state.message} 
       onChange={ev => this.setState({message: ev.target.value})}/>

Initially, your this.state.username/message are undefined, thus those two components are thought to be uncontrolled by React.

Refer to following docs for

  • Forms -> Controlled - Official React Doc
  • Uncontrolled Components - Official React Doc

Once your set values for those states in onChange, React now thinks that you are changing the controlled component values as your error message showed.

Warning: A component is changing an uncontrolled input of type text to be controlled...

So what you need to do is to declare those two state values in OpenedUser with the rest of existing state, hidden.

class OpenedUser extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hidden: false,
      // empty/props or other sensible default value
      message: "",
      // empty/props or other sensible default value
      username: ""
    };
  }
  // omitted for brevity...
}

I am sorry 😅 I haven't been able to test the code above.

like image 61
dance2die Avatar answered Dec 12 '25 10:12

dance2die



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!