从ReactJS状态设置textarea滚动

问题描述 投票:0回答:1

我正在尝试使用React组件的状态来控制textarea的滚动位置,但是当我调用setState()时它不会移动。

这是一个示例,单击链接应滚动到textarea的顶部,但它不会移动。使用滚动条滚动可以记录位置,并且字段会移动。单击该链接会将消息写入控制台,但滚动位置不会移动。我将此方法基于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来控制滚动位置,但我想通过组件状态或组件属性来控制它。 (最终,我想同步两个textareas的滚动。)我也尝试使用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>
javascript reactjs scrollbar
1个回答
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我的同步滚动的原始目标一样。

© www.soinside.com 2019 - 2024. All rights reserved.