Установить прокрутку текстовой области из состояния ReactJS - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь контролировать положение прокрутки текстовой области, используя состояние компонента React, но он не перемещается, когда я вызываю setState().

Вот пример, когда нажатие на ссылку должно прокручиватьсяна вершину текстовой области, но она не двигается.Прокрутка с помощью полосы прокрутки может регистрировать позиции, и поле перемещается.При нажатии на ссылку записывается сообщение на консоль, но позиция прокрутки не перемещается.Я основывал этот подход на контролируемых компонентах , описанных в документации ReactJS.

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>

Я могу управлять положением прокрутки, используя ссылку и устанавливая ее scrollTop, но я хочу управлять им через состояние компонента илисвойства компонентов.(В конце концов, я хочу синхронизировать прокрутку двух текстовых областей.) Я также попытался использовать библиотеку react-scroll-sync , но она плохо работает с ячейками таблицы.

Вот примеркоторый контролирует позицию, используя ссылку и ее 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 Ответ

1 голос
/ 26 марта 2019

Томми Мэй объяснил в комментарии, что scrollTop не является атрибутом HTML, поэтому я не могу связать его напрямую с состоянием или свойствами компонента.Однако я обнаружил, что метод componentDidUpdate() можно использовать для обработки изменений состояния или свойств.

Вот обновленный пример, в котором используется 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>

Это не особенно полезно в этом примере, но полезно, когда вы хотите использовать свойства вместо локального состояния, как в этот ответ Я опубликовал для своей первоначальной цели синхронизированной прокрутки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...