change scrollTop in reactjs

前端 未结 4 1384
隐瞒了意图╮
隐瞒了意图╮ 2021-01-04 03:36

I just learn react, and want to achieve a function : both A,B are components, if A scroll, then B scroll

The following is my code

<

相关标签:
4条回答
  • 2021-01-04 04:00

    2019's answer

    First, the fix:

    const resetScrollEffect = ({ element }) => {
      element.current.getScrollableNode().children[0].scrollTop = 0
    }
    
    const Table = props => {
      const tableRef = useRef(null)
      useEffect(() => resetScrollEffect({ element: tableRef }), [])
      return (
        <Component>
          <FlatList
            ref={someRef}
          />
        </Component>
      )
    }
    

    Second, a little explanation:

    Idk what is your reason why you got here but I have used flex-direction: column-reverse for my FlatList (it's a list of elements). And I need this property for z-index purposes. However, browsers set their scroll position to the end for such elements (tables, chats, etc.) - this may be useful but I don't need that in my case.

    Also, example is shown using React Hooks, but you can use older more traditional way of defining refs

    0 讨论(0)
  • 2021-01-04 04:09

    this.refs is deprecated. use reactjs.org/docs/refs-and-the-dom.html#creating-refs

    import React from 'react';
    
    class SomeComponent extends React.Component {
      constructor(props) {
        super(props);
        this.resultsDiv = React.createRef();
      }
    
      someFunction(){
         this.resultsDiv.current.scrollIntoView({behavior: 'smooth'});
    
         // alternative:
         // this.resultsDiv.current.scrollTop = 0;
      }
    
      render() {
        return (
          <div ref={this.resultsDiv} />
        );
      }
    }
    
    export default SomeComponent;
    
    
    
    0 讨论(0)
  • 2021-01-04 04:12

    There are a number of patterns to achieve this. This sample is what I came up with to get you up and going.

    First create a component class which has an oversize element for scroll effect. When dragging the scroll bar, this component calls its handleScroll React property to notify its parent component, with the value of scrollTop.

    var Elem = React.createClass({
        render() {
            return (
                <div ref="elem"
                    onScroll={ this.onScroll }
                    style={{ width: "100px", height: "100px", overflow: "scroll" }}>
                    <div style={{ width: "100%", height: "200%" }}>Hello!</div>
                </div>
            );
        },
        componentDidUpdate() {
            this.refs.elem.scrollTop = this.props.scrollTop;
        },
        onScroll() {
            this.props.handleScroll( this.refs.elem.scrollTop );
        }
    });
    

    The parent component, aka wrapper, keeps the scroll top value in its state. Its handleScroll is passed to the child components as callback. Any scroll on the child elements triggers the callback, sets the state, results in a redraw, and updates the child component.

    var Wrapper = React.createClass({
        getInitialState() {
            return {
                scrollTop: 0
            }
        },
        render() {
            return (
                <div>
                    <Elem scrollTop={ this.state.scrollTop } handleScroll={ this.handleScroll } />
                    <Elem scrollTop={ this.state.scrollTop } handleScroll={ this.handleScroll } />
                </div>
            );
        },
        handleScroll( scrollTop ) {
            this.setState({ scrollTop });
        }
    });
    

    And render the wrapper, presuming an existing <div id="container"></div>.

    ReactDOM.render(
        <Wrapper />,
        document.getElementById('container')
    );
    
    0 讨论(0)
  • 2021-01-04 04:12

    Here's an updated version of Season's answer, including a runnable snippet. It uses the recommended method for creating refs.

    class Editor extends React.Component {
        constructor(props) {
            super(props);
            this.content = React.createRef();
            this.handleScroll = this.handleScroll.bind(this);
        }
    
        componentDidUpdate() {
            this.content.current.scrollTop = this.props.scrollTop;
        }
        
        handleScroll() {
            this.props.onScroll( this.content.current.scrollTop );
        }
    
        render() {
            let text = 'a\n\nb\n\nc\n\nd\n\ne\n\nf\n\ng';
            return <textarea
                ref={this.content}
                value={text}
                rows="10"
                cols="30"
                onScroll={this.handleScroll}/>;
        }
    }
    
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {scrollTop: 0};
            this.handleScroll = this.handleScroll.bind(this);
        }
    
        handleScroll(scrollTop) {
            this.setState({scrollTop: scrollTop});
        }
    
        render() {
            return <table><tbody>
                <tr><th>Foo</th><th>Bar</th></tr>
                <tr>
                    <td><Editor
                        scrollTop={this.state.scrollTop}
                        onScroll={this.handleScroll}/></td>
                    <td><Editor
                        scrollTop={this.state.scrollTop}
                        onScroll={this.handleScroll}/></td>
                </tr>
            </tbody></table>;
        }
    }
    
    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    );
    <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>

    0 讨论(0)
提交回复
热议问题