最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Scroll to bottom of textarea - Stack Overflow

programmeradmin8浏览0评论

I am apending text to a textarea then attempting to scroll to the bottom to keep the latest within view. However, in doing this I appear to be crashing the browser / running out of memory. Can anyone help optimise this code?

//Appending text and calling scroll function
this.setState({ transcriptText: this.state.transcriptText + resp.log })
this.scrollToBottom();

//Textarea
<TextArea
  ref={textLog => this.textLog = textLog}
  autosize={{ minRows: 10, maxRows: 15 }}
  value={this.state.transcriptText}
>
</TextArea>

//Scrolling
scrollToBottom = () => {
    const textLogContainer = ReactDOM.findDOMNode(this.textLog);
    if(textLogContainer){
        textLogContainer.scrollTop = textLogContainer.scrollHeight;
    }
};

Full

componentDidMount() {
    const socket = io.connect(process.env.REACT_APP_API_URL, { transports: ['websocket'] });
    socket.emit('onboarding', { id: uploadId });
    socket.on('transcript_log', function (resp) {
        this.setState({ transcriptText: this.state.transcriptText + resp.log })
        this.scrollToBottom();
    }.bind(this));
}

Thanks

I am apending text to a textarea then attempting to scroll to the bottom to keep the latest within view. However, in doing this I appear to be crashing the browser / running out of memory. Can anyone help optimise this code?

//Appending text and calling scroll function
this.setState({ transcriptText: this.state.transcriptText + resp.log })
this.scrollToBottom();

//Textarea
<TextArea
  ref={textLog => this.textLog = textLog}
  autosize={{ minRows: 10, maxRows: 15 }}
  value={this.state.transcriptText}
>
</TextArea>

//Scrolling
scrollToBottom = () => {
    const textLogContainer = ReactDOM.findDOMNode(this.textLog);
    if(textLogContainer){
        textLogContainer.scrollTop = textLogContainer.scrollHeight;
    }
};

Full

componentDidMount() {
    const socket = io.connect(process.env.REACT_APP_API_URL, { transports: ['websocket'] });
    socket.emit('onboarding', { id: uploadId });
    socket.on('transcript_log', function (resp) {
        this.setState({ transcriptText: this.state.transcriptText + resp.log })
        this.scrollToBottom();
    }.bind(this));
}

Thanks

Share Improve this question edited Dec 1, 2017 at 14:41 Elliot Reeve asked Dec 1, 2017 at 14:22 Elliot ReeveElliot Reeve 9416 gold badges23 silver badges40 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 9

It's easier to use the newer React.createRef() and use componentDidUpdate() as a trigger:

constructor(props) {
    super(props);

    this.textLog = React.createRef();
}

componentDidUpdate() {
    this.textLog.current.scrollTop = this.textLog.current.scrollHeight;
}

render() {
    return(
        <textarea ref={this.textLog} value={this.state.transcriptText} />
    );
}

You don't need to do ReactDOM.findDOMNode when you have a ref, change it to just check if the ref is null and then change scrollTop.

Like this

scrollToBottom = () => {
    if(this.textLog){
        this.textLog.scrollTop = this.textLog.scrollHeight;
    }
};

I struggled long and hard to figure this out. I've got a ReactJS app that reads logfiles from services running on a machine, and I wanted the most recent log message to scroll into view. Here is a somewhat complete example of my LogFileTextBox control using React Hooks:

import { Row } from "react-bootstrap";
import { Col } from "react-bootstrap";
import { Container } from "react-bootstrap";
import { useRef, useEffect } from "react";

const LogFileTextBox = (props) => {
  const logText = props.logText;
  const logFileName = props.logFileName;
  const textArea = useRef();
  
  // After render, this scrolls the textArea to the bottom.
  useEffect(() => {
    const area = textArea.current;
    area.scrollTop = area.scrollHeight;
  });

  return (
    <div>
      <Container fluid>
        <Row>&nbsp;</Row>
        <Row>&nbsp;</Row>
        <Row>
          <Col></Col>
          <Col>
            <h6>Current Log: {logFileName}</h6>
          </Col>
          <Col></Col>
        </Row>
        <Row>
          <Col>
            <textarea                 
              value={logText}
              readOnly={true}
              ref={textArea}    // This links the useRef() hook to this object in the dom
            />
          </Col>
        </Row>
      </Container>
    </div>
  );
};

export default LogFileTextBox;
发布评论

评论列表(0)

  1. 暂无评论