【问题标题】:How do I get the ref value from a drop down box passed to its sibling component?如何从传递给其兄弟组件的下拉框中获取 ref 值?
【发布时间】:2018-09-30 04:11:22
【问题描述】:

我正在使用 socket.io 构建一个聊天应用程序,并且我有一个仪表板组件,其中包含两个名为 Room.js 和 Chat.js 的子组件。我的房间组件负责选择您要加入的聊天室。在选择标签中,我给它一个 ref 以了解该值。如何在我的 Chat 组件中访问该值,以便我只能在那个房间发出消息?

我在第一个 sn-p 下发布了一个工作版本,其中包含消息传递和所有内容都在一个组件中,但我需要它们是单独的组件。

我还是一个 react 初学者。

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

【问题讨论】:

  • 尝试发布一个最小的工作示例。删除所有不相关的代码、空格和 cmets。
  • 抱歉第一次在这里发帖

标签: javascript reactjs socket.io ref chatroom


【解决方案1】:

这是状态而非引用的一个很好的用例,我个人避免使用引用,状态更具响应性。

点击房间后,你可以设置房间的状态是或唱歌,然后你可以将此id作为道具传递给聊天组件。

【讨论】:

  • 聊天和房间组件是同级的,所以我应该在我的父仪表板组件中跟踪状态?
  • 是的,这样会更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
相关资源
最近更新 更多