javascript - 使用 React 在两个 div 中显示提交的文本

标签 javascript reactjs

我对 React 和构建原型(prototype)聊天应用程序还很陌生。同一页面上有两个窗口,一个是帮助代理,另一个是客户(或请求帮助的人)。当代理或客户输入消息时,该消息应出现在两个窗口中。但是,我当前的版本只在每个窗口中显示关联的用户,而不是在两个窗口中显示消息。还需要保持提交按钮处于非事件状态,直到消息框中有文本为止。

我试过使用 <button type="button" disabled={!this.state.email}>Button</button>并添加 value={this.state.message} onChange={this.handleChange}到输入字段,但这已被证明是无效的。

因此,第一件事是如何在任一用户输入消息时让消息显示在两个窗口中。最后,如何正确设置按钮状态?

我的应用程序是这样分解的:

MessageList.jsMessageForm.js是注入(inject) User.js 的组件和 Agent.js ,然后注入(inject) App.js

MessageList.js

class MessageList extends Component {
  componentDidUpdate = () => {
    this.node.scrollTop = this.node.scrollHeight
  }

  render() {
    return (
      <div className="MessageList" ref={(node) => (this.node = node)}>
        {this.props.messages.map((message, i) => (
            <Message key={i} {...message} />
        ))}
      </div>
    )
  }
}

export default MessageList

MessageForm.js

class MessageForm extends Component {
  static propTypes = {
    onMessageSend: PropTypes.func.isRequired,
  }

  componentDidMount = () => {
    this.input.focus()
  }

  handleFormSubmit = (event) => {
    event.preventDefault()
    this.props.onMessageSend(this.input.value)
    this.input.value = ""
  }

  render() {
    return (
      <form className="MessageForm" onSubmit={this.handleFormSubmit}>
        <div className="input-container">
          <input
            type="text"
            ref={(node) => (this.input = node)}
            placeholder="Enter Message..."
          />
        </div>
        <div className="button-container">
          <button type="submit">
            Send
          </button>
        </div>
      </form>
    )
  }
}

export default MessageForm

User.js

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

  render() {
    return (
      <div className="User">
        <header>
          <p>You</p>
        </header>
        <MessageList messages={this.state.messages} />
        <MessageForm onMessageSend={this.handleNewMessage} />
      </div>
    );
  }
}

export default User;

Agent.js

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

  render() {
    return (
      <div className="Agent">
        <header>
          <p>Agent</p>
        </header>
        <MessageList messages={this.state.messages} />
        <MessageForm onMessageSend={this.handleNewMessage} />
      </div>
    );
  }
}

export default Agent;

App.js

class App extends Component {
  static propTypes = {
    messages: PropTypes.arrayOf(PropTypes.object)
  }

  static defaultProps = {
    messages: [],
  }

  handleNewMessage = (text) => {
     this.setState({
        messages: [...this.state.messages, {me: true, author: "Me", body: text}, {me:  false, author: "Agent", body: text}]
     })
  }
  render() {
    return (
      <div className="App">
        <div className="agentWindow">
          <Agent />
        </div>
        <div className="userWindow">
          <User />
        </div>
      </div>
    );
  }
}

export default App;

Message.js

class Message extends Component {
  static propTypes = {
    author: PropTypes.string,
    body: PropTypes.string.isRequired,
    me: PropTypes.bool,
  }

  render() {
    const classes = classNames('Message', {
      log: !this.props.author,
      me: this.props.me
    })

    return (
      <div className={classes}>
        {this.props.author && (
          <span className="author">{this.props.author}:</span>
        )}
        {this.props.body}
      </div>
    )
  }
}

export default Message

最佳答案

您的消息没有显示在两个窗口上,因为您在 AgentUser 内部创建状态,并且它们是独立的。因此,如果您向一个状态添加一条消息,它不会添加到另一个状态。你可以看看Redux在组件之间共享状态,或者你可以将你的 messages 状态和你的 handleNewMessage 方法放在 App 中并将它们作为 Prop 传递给 AgentUser,这样他们将使用相同的状态。看一看:

App.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      messages: []
    }
    this.handleNewMessage = this.handleMessage.bind(this);
  }

  static propTypes = {
    messages: PropTypes.arrayOf(PropTypes.object)
  }

  handleNewMessage = (text) => {
     this.setState({
        messages: [...this.state.messages, {me: true, author: "Me", body: text}, {me:  false, author: "Agent", body: text}]
     })
  }
  render() {
    return (
      <div className="App">
        <div className="agentWindow">
          <Agent messages={this.state.messages} handleNewMessage={this.handleNewMessage} />
        </div>
        <div className="userWindow">
          <User messages={this.state.messages} handleNewMessage={this.handleNewMessage} />
        </div>
      </div>
    );
  }
}

User.js

class User extends Component {
  render() {
    return (
      <div className="User">
        <header>
          <p>You</p>
        </header>
        <MessageList messages={this.props.messages} />
        <MessageForm onMessageSend={this.props.handleNewMessage} />
      </div>
    );
  }
}

export default User;

Agent 也是如此。

关于禁用按钮,你可以添加一个受控输入,它看起来像这样:

class ExampleForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() {
    return (
      <form>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <button type="submit" disabled={this.state.message === ''}>Send<button/>
      </form>
    );
  }
}

关于javascript - 使用 React 在两个 div 中显示提交的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48846635/

相关文章:

javascript - jquery中订单总数乘以订单数量

javascript - 如何遍历包含小于迭代器值的数组

javascript - 禁止用户在所有浏览器的控制台中运行 javascript

reactjs - 容器组件中的 PropType

javascript - 提交后清除url

javascript - 滚动后重新定位 DIV

javascript - 如何在保存到 Mongoose (ExpressJS) 之前格式化模型中的数据

reactjs - react 全局记忆化

javascript - 使用 Node.js 中的 TLS/SSL 隐式加密连接到 FTP 服务器

javascript - React hooks、函数组件和 Redux