Как я могу получить значение ref из выпадающего списка, переданного его братскому компоненту? - PullRequest
0 голосов
/ 30 сентября 2018

Я создаю приложение чата с socket.io, и у меня есть компонент панели мониторинга с двумя дочерними компонентами, который называется Room.js и Chat.js.Компонент «Моя комната» отвечает за выбор комнаты чата, в которую вы хотите вступить.В теге select я даю ссылку, чтобы узнать значение.Как мне получить доступ к этому значению в моем компоненте чата, чтобы я мог отправлять сообщения только в этой комнате?

Я разместил рабочую версию ниже первого фрагмента с сообщениями и всем в одном компоненте, но мне нужно, чтобы они былиотдельные компоненты.

Я все еще новичок в реакции.

class Room extends Component {
  constructor(props) {
    super(props);
    this.state = {
      
      
    };

    
    
    this.joinRoom = this.joinRoom.bind(this);
    this.joinSuccess = this.joinSuccess.bind(this);
  }



  componentDidMount() {
    this.socket = io("http://localhost:4444")
    this.socket.on('message dispatched', this.updateMessages)
    this.socket.on('welcome', this.setUserId)
    this.socket.on('room joined', this.joinSuccess)
    this.joinRoom()
  }

  

  joinRoom() {
    this.socket.emit('join room', {
      room: this.refs.room.value
    })
    
  }

  joinSuccess(room) {
    console.log("you successfully joined room " + room)
  }

 

  
 
  render() {
    return (
      <Background>
        <Container className="animated fadeInDownBig">
          {" "}
          <Logo> Sketchful </Logo>
          <Info>Join a Room</Info>
          <select ref='room' defaultValue='Global' onChange={this.joinRoom}>
            <option>Global</option>
            <option>Stark</option>
            <option>Lannister</option>
            <option>Targaryen</option>
            <option>Tyrell</option>
            <option>Baratheon</option>
            <option>Greyjoy</option>
          </select>

           
        
        
          <Link to="/dashboard">
            <Button onClick={this.props.handleEnter}> Enter </Button>
          </Link>{" "}
          
        </Container>
      </Background>
    );
  }
}

export default Room;

Если я сделаю это, это сработает, но я хочу, чтобы компонент Chat отвечал за отправку сообщений.

class Room extends Component {
  constructor(props) {
    super(props);
    this.state = {
      messages: [],
      
    };

    
    this.updateMessages = this.updateMessages.bind(this);
    this.sendMessage = this.sendMessage.bind(this);
    this.joinRoom = this.joinRoom.bind(this);
    this.joinSuccess = this.joinSuccess.bind(this);
  }



  componentDidMount() {
    this.socket = io("http://localhost:4444")
    this.socket.on('message dispatched', this.updateMessages)
    this.socket.on('welcome', this.setUserId)
    this.socket.on('room joined', this.joinSuccess)
    this.joinRoom()
  }

  updateMessages(message) {
    const updatedMessages = this.state.messages.slice()
    updatedMessages.push(message)
    this.setState({
      messages: updatedMessages
    })
  }

  sendMessage() {
    this.socket.emit('message sent', {
      message: this.refs.message.value,
      room: this.refs.room.value
    })
    this.refs.message.value = '';
  }

  joinRoom() {
    this.socket.emit('join room', {
      room: this.refs.room.value
    })
    
  }

  joinSuccess(room) {
    console.log("you successfully joined room " + room)
  }

 

  
 
  render() {
    const messages = this.state.messages.map((e,i) => {
      const styles = e.user === this.state.userID ? {alignSelf: "flex-end", backgroundColor: "#2d96fb", color: "white"} : {alignSelf: "flex-start", backgroundColor: "#e5e6ea"}
      return (
        <p key={i} style={styles}>{e.message}</p>
      )
    })
 console.log(this.props.room)



 
    return (
      <Background>
        <Container className="animated fadeInDownBig">
          {" "}
          <Logo> Sketchful </Logo>
          <Info>Join a Room</Info>
          <select ref={this.props.room} defaultValue='Global' onChange={this.joinRoom}>
            <option>Global</option>
            <option>Stark</option>
            <option>Lannister</option>
            <option>Targaryen</option>
            <option>Tyrell</option>
            <option>Baratheon</option>
            <option>Greyjoy</option>
          </select>

           
        <div className="messages">
          {messages}
        </div>
        <div className="input">
          <input ref="message" />
          <button onClick={this.sendMessage}>Send</button>
        </div>
          <Link to="/dashboard">
            <Button onClick={this.props.handleEnter}> Enter </Button>
          </Link>{" "}
          
        </Container>
      </Background>
    );
  }
}

export default Room;

class Chat extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // words: ["cat", "dog", "sun", "cup", "pie", "bug", "snake", "tree"],
      messages: [],
      message: "",
      correct: '',
      typing: false,
      timeout: undefined,
      
    };
    // this.socket = io.connect("http://localhost:4444");
    this.handleEnter = this.handleEnter.bind(this)
    

  }

  
  componentDidMount() {
    this.socket = io.connect("http://localhost:4444");

    this.socket.on("chat", msg => {
      let messages = this.state.messages
      messages.push(msg)
      this.setState({
        messages: messages 
      })
      
    });
  }

  componentWillUnmount() {
    this.socket.close();
  }

  updateMessage = e => {
    this.setState({
      message: e.target.value
    });
  };

  async handleEnter (e) {
    
    if(this.state.message) {
    if (e.key === "Enter" ) {
      this.socket.emit("chat", {
        name: this.props.user.username,
        message: this.state.message,
        timestamp: new Date().toISOString(),
       


        
        
      });
      this.setState({
        message: ""
      });

      const response = await axios.post(`/api/create`, {message: this.state.message})
      this.props.getUserData(response)

      let words = this.props.words;
      for (let i = 0; i < words.length; i++) {
        if (this.state.message === this.props.word) {
          this.setState({
            correct: 'Correct!'
          })
        }
      }
      
    }
  }
  };


   handleClick = () => {
     console.log('clicked')
   }
  

  render() {
console.log(this.state.message)

    return (
      
      <div className="chat">
        <Messages messages={this.state.messages} user={this.props.user.username}/>
        <p>{this.state.correct}</p>

        

        <textarea
          value={this.state.message}
          onKeyPress={this.handleEnter}
          onChange={this.updateMessage}
          className="message"
          placeholder="Type a message... "
          type="text"
        />

        
        
      </div>
      
    );
  }
}

function mapStateToProps(state) {
  return {
    user: state.user,
    id: state.id
  };
}

export default connect(
  mapStateToProps,
  { getUserData }
)(Chat);
Сервер

io.on("connection", socket => {
  console.log("a user connected");
  socket.on("disconnect", function() {
    console.log("user disconnected");
  });

   
  socket.on('join room', data => {
    console.log('Room joined', data.room)
    
    socket.join(data.room);
    io.to(data.room).emit('room joined', data.room);
  })

  socket.on("chat", data => {
      console.log(data.room)
    io.in(data.room).emit("chat", data);
  });

1 Ответ

0 голосов
/ 30 сентября 2018

Это хороший вариант использования для состояния, а не для ссылок, лично я избегаю использования ссылок, состояние более отзывчиво.

При нажатии на комнату, вы можете установить состояние с комнатой или пением, а затем вы можете передатьэтот идентификатор в качестве опоры для компонента чата.

...