Add Scroll Bar to a Box

Asked

Viewed 764 times

3

I am doubtful in my code, in it I will add a chat field, and in this chat the box should have a maximum size, and if in the case when adding the messages exceeds this value, it should create a scroll bar, but this is not working.

In the browser I accuse these errors: Typeerror: Cannot read Property 'scrollHeight' of null

> 43 | ReactDOM.findDOMNode(this.refs.data). scrollTop = ReactDOM.findDOMNode(this.refs.data). scrollHeight;

Follow the code:

import React, {Component} from 'react';
import './Chat.css';
import { If, Then, Else } from 'react-if';
import ReactDOM from 'react-dom';
import Message from './Message.js';

class Chat extends React.Component {

  constructor(props) {
        super(props);

        this.state = {
          data:[],
            chats: [] };

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

componentDidMount(){
        let URL = 'stackTeste'

           fetch(URL)
           .then(function(response) {
              let data = response.json()
              return data;
           })
           .then((json) => {
              console.log('Vetor JSON: ', json)
              this.setState({data : json});
           })
           .catch(function(ex) {
              console.log('parsing failed', ex)
           })
           this.scrollToBot();
  }


  componentDidUpdate() {
          this.scrollToBot();
      }

      scrollToBot() {
          ReactDOM.findDOMNode(this.refs.data).scrollTop = ReactDOM.findDOMNode(this.refs.data).scrollHeight;
      }


  submitMessage(e) {
      e.preventDefault();

      this.setState({
          chats: this.state.chats.concat([{
              username: "Eu",
              content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,
              img: "https://www.sitelovers.com.br/franquias/2/0e01938fc48a2cfb5f2217fbfb00722d/36452e720502e4da486d2f9f6b48a7bb/editor/image/circulo_laranja.png",
              time: "1 min ago",
          }])
      }, () => {
          ReactDOM.findDOMNode(this.refs.msg).value = "";
      });
  }


render(){
  const username = "Kevin su";
        const { chats } = this.state;
    return(
    <div className="container">
        <div className="chatroom ">
           <div className="box-header with-border" >
           <i className="fa fa-commenting-o fa-2x">  </i>
               <h3 className="box-title">Chat</h3>
           </div>
           {
                 this.state.data.map((obj) =>
                  <div className="box-body">
                      <div className="direct-chat-msg undefined">
                          <div className="direct-chat-info clearfix">
                  </div>
                      <If condition={obj.displayPortraitLeft == true}>
                      <Then>
                            <div className="direct-chat-info clearfix">
                              <span className="direct-chat-name pull-left">{obj.userName}</span>
                              <span className="direct-chat-timestamp pull-left">{obj.time}</span>
                            </div>
                              <img className="direct-chat-img" src={obj.portrait} alt="message user image"/>
                      </Then>
                      <Else>
                            <div nameClass="direct-chat-msg right">
                                <div className="direct-chat-info clearfix">
                                    <span className="direct-chat-name pull-right">{obj.userName}</span>
                                    <span className="direct-chat-timestamp pull-right">{obj.time}</span>
                                </div>
                                    <img className="direct-chat-img-right" src={obj.portrait} alt="message user image"/>
                            </div>
                      </Else>
                      </If>
                      <div className="direct-chat-text">{obj.message}</div>

                  </div>
                  </div>
                 )

             }
             {
                                  chats.map((chat) =>
                                  <div className="box-body">
                                      <div className="direct-chat-msg undefined">
                                          <div className="direct-chat-info clearfix">
                                  </div>
                                     <Message chat={chat} user={username} />
                                     </div>
                                     </div>
                                                )
                                      }
              <div className="input-group">
                            <form onSubmit={(e) => this.submitMessage(e)}>
                                 <input type="text" ref="msg" className="form-control"/>
                                 <span className="input-group-btn">
                                 <input type="submit" className="btn btn-flat btn-primary" value="Submit" />
                                 </span>
                             </form>
                             </div>
    </div>
  </div>
    );
  }
}
export default Chat;

1 answer

1

These are some of the causes of returning this error:

  1. The element has not been rendered
  2. The informed reference is not the same as the element, example:

    <div ref="box">
    

    When redeeming the element:

    ReactDOM.findDOMNode(this.refs.boxx)
    

    or the other way around.

The correct is for you to check whether the element has been rendered and whether the reference is correct:

scrollToBot() {
    const check= ReactDOM.findDOMNode(this.refs.data);
    if (check) {
        check.scrollTop = check.scrollHeight;
    }
}

To illustrate created two projects, they are simple, just an object containing some texts and a button, that when clicking moves the scroll block box.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      mensagens: [
        'Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem',
        'Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem',
        'Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem',
        'Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem','Mensagem',
      ]
    };
    this.moverScroll = this.moverScroll.bind(this);
  }
  moverScroll(event) {
    // Abaixo verificamos se a div `box` foi renderizada
    // Caso tenha sido, move o scroll para baixo
    const check = ReactDOM.findDOMNode(this.refs.box);
    if (check){
      check.scrollTop = check.scrollHeight;
    }
  }
  render() {
    return(
      <div>
        <div ref="box" style={styles.box}>
          {this.state.mensagens.map((msg, i) => (
            <p style={styles.msg} key={i}>{msg} {i}</p>
          ))}
        </div>
        <button onClick={this.moverScroll}>CLIQUE PARA MOVER O SCROLL</button>
      </div>
    )
  }
}

You can see running Example with verification and Example without verification.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.