@tj57

Как правильно рендерить компонент в зависимости от состояния в React?

У меня есть компонент, отвечающий за чат :
5c277f3e85178697502586.jpeg
import React from "react";
import io from "socket.io-client";

class Chat extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            username: '',
            message: '',
            messages: []
        };

        this.socket = io('localhost:5000');

        this.socket.on('RECEIVE_MESSAGE', function(data){
            addMessage(data);
        });

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

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

        }
    }
    render(){
        return (
            <div className="container">
                <div className="row">
                    <div className="col-4">
                        <div className="card">
                            <div className="card-body">
                                <div className="card-title">Global Chat</div>
                                <hr/>
                                <div className="messages">
                                    {this.state.messages.map(message => {
                                        return (
                                            <div>{message.author}: {message.message}</div>
                                        )
                                    })}
                                </div>

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

export default Chat;


Мне нужно разделить этот компонент на 2 : первый - поле для ввода имени пользователя и кнопка "Присоединиться к чату", второй - сам чат, но уже без поля для ввода имени. Сначала рендерится первый компонент, а после ввода имени и его отправки - рендерится второй. Как правильно это реализовать ? Я сделал так, но оно не работает. И как реализовать метод Join, который срабатывает при нажатии на кнопку в первом компоненте и добавляет имя пользователя в состояние?

const ChatComponent = () => {
          return (
          <div className="container">
            <div className="row">
              <div className="col-4">
                <div className="card">
                  <div className="card-body">
                      <div className="card-title">Chat</div>
                      <hr/>
                      <div className="messages">
                        {this.state.messages.map(message => {
                          return (
                              <div>{message.author}: {message.message}</div>
                                )
                          })}
                      </div>
                  </div>
                  <div className="card-footer">
                      <input type="text" placeholder="Message" className="form-control"/>
                      <br/>
                      <button onClick={ this.sendMessage} className="btn btn-primary form-control">Send</button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          );
       }

      const JoinComponent = () => {
        return (
          <div className="card-footer">
            <input type="text" placeholder="Username" className="form-control"/>
            <br/>
            <button onClick={this.Join} className="btn btn-primary form-control">Join chat</button>
          </div>
        );
      }


render() {
      const username = this.state.username;
      return (
        <div>
        {this.state.username ? (
         <ChatComponent/>
          ) : (
         <JoinComponent />
      )};
      </div>
    );
  }
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
@Magrian
Почитайте про props, да и вообще документацию в целом.

Решение вашей проблемы в моем видении:
import React from "react";
import io from "socket.io-client";
class ChatComponent extends React.Component {
	state = { message: "" }
	render() {
		return (
			<div className="container">
				<div className="row">
					<div className="col-4">
						<div className="card">
							<div className="card-body">
								<div className="card-title">Chat</div>
								<hr />
								<div className="messages">
									{this.props.messages.map(message => {
										return (
											<div>{message.author}: {message.message}</div>
										)
									})}
								</div>
							</div>
							<div className="card-footer">
								<input
									type="text"
									placeholder="Message"
									className="form-control"
									value={this.state.message}
									onChange={ev => this.setState({ message: ev.target.value })} />
								<br />
								<button onClick={() => this.props.sendMessage(this.state.message)} className="btn btn-primary form-control">Send</button>
							</div>
						</div>
					</div>
				</div>
			</div>
		);
	}
}

class JoinComponent extends React.Component {
	state = { username: "" }
	render() {
		return (
			<div className="card-footer">
				<input
					type="text"
					placeholder="Username"
					className="form-control"
					value={this.state.username}
					onChange={ev => this.setState({ username: ev.target.value })} />
				<br />
				<button onClick={() => this.props.click(this.state.username)} className="btn btn-primary form-control">Join chat</button>
			</div>
		);
	}
}

class Chat extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			username: '',
			messages: []
		};

		this.socket = io('localhost:5000');

		this.socket.on('RECEIVE_MESSAGE', function (data) {
			addMessage(data);
		});

		const addMessage = data => {
			console.log(data);
			this.setState({ messages: [...this.state.messages, data] });
			console.log(this.state.messages);
		};
	}
	
	sendMessage = (message) => {
		this.socket.emit('SEND_MESSAGE', {
			author: this.state.username,
			message: message
		})
		this.setState({ message: '' });
	}
	
	joinToChat = (username) => {
		this.setState({ username })
	}

	render() {
		if (this.state.username) {
			return <ChatComponent 
						messages={this.state.messages} 
						sendMessage={this.sendMessage} />}
						
		else return <JoinComponent click={this.joinToChat} />
	}
}

export default Chat;
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы