从ReactJS状态设置textarea滚动

时间:2019-03-26 03:40:28

标签: javascript reactjs scrollbar

我试图使用React组件的状态来控制文本区域的滚动位置,但是当我调用setState()时它不会移动。

在此示例中,单击链接应滚动到文本区域的顶部,但不会移动。使用滚动条滚动可以记录位置,并且字段会移动。单击链接会将消息写入控制台,但滚动位置不会移动。我将这种方法基于ReactJS文档中所述的controlled components

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {scrollTop: 0};
    this.handleScroll = this.handleScroll.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleScroll() {
    let scrollTop = this.refs.content.scrollTop;
    console.log(scrollTop);
    this.setState({scrollTop: scrollTop});
  }
  
  handleClick(e) {
    e.preventDefault();
    console.log('Clicked.');
    this.setState({scrollTop: 0});
  }
  
  render() {
    let text = 'a\n\nb\n\nc\n\nd\n\ne\n\nf\n\ng';
    return <p><textarea
        ref="content"
        value={text}
        rows="10"
        cols="30"
        scrollTop={this.state.scrollTop}
        onScroll={this.handleScroll}/>
      <a href="#" onClick={this.handleClick}>
        Scroll to top
      </a></p>;
  }
}

ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
.as-console-wrapper { max-height: 10% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我可以通过使用ref并设置其scrollTop来控制滚动位置,但是我想通过组件状态或组件属性来控制滚动位置。 (最终,我想同步两个文本区域的滚动。)我也尝试使用react-scroll-sync library,但是它不适用于表格单元格。

下面是一个使用ref及其scrollTop控制位置的示例:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleScroll = this.handleScroll.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleScroll() {
    let scrollTop = this.refs.content.scrollTop;
    console.log(scrollTop);
  }
  
  handleClick(e) {
    e.preventDefault();
    console.log('Clicked.');
    this.refs.content.scrollTop = 0;
  }
  
  render() {
    let text = 'a\n\nb\n\nc\n\nd\n\ne\n\nf\n\ng';
    return <p><textarea
        ref="content"
        value={text}
        rows="10"
        cols="30"
        onScroll={this.handleScroll}/>
      <a href="#" onClick={this.handleClick}>
        Scroll to top
      </a></p>;
  }
}

ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
.as-console-wrapper { max-height: 10% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

1 个答案:

答案 0 :(得分:1)

汤米·梅(Tommy May)在评论中解释说scrollTop不是HTML属性,因此我无法将其直接链接到组件状态或属性。但是,我发现componentDidUpdate() method可用于处理状态或属性的更改。

这是使用componentDidUpdate()的更新示例:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {scrollTop: 0};
    this.content = React.createRef();
    this.handleScroll = this.handleScroll.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleScroll() {
    let scrollTop = this.content.current.scrollTop;
    console.log(scrollTop);
    this.setState({scrollTop: scrollTop});
  }
  
  handleClick(e) {
    e.preventDefault();
    console.log('Clicked.');
    this.setState({scrollTop: 0});
  }
  
  componentDidUpdate() {
    this.content.current.scrollTop = this.state.scrollTop;
  }
  
  render() {
    let text = 'a\n\nb\n\nc\n\nd\n\ne\n\nf\n\ng';
    return <p><textarea
        ref={this.content}
        value={text}
        rows="10"
        cols="30"
        onScroll={this.handleScroll}/>
      <a href="#" onClick={this.handleClick}>
        Scroll to top
      </a></p>;
  }
}

ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
.as-console-wrapper { max-height: 10% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

这在此示例中并不是特别有用,但是当您要使用属性而不是本地状态时,它很有用,例如我出于同步滚动的最初目标发布的this answer