Change scrollTop in reaction

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

Below is my code

<A onScroll="handleScroll"></A>

 //what i write now handleScroll: function(event){ var target = event.nativeEvent.target; //do something to change scrollTop value target.scrollTop += 1; // it looks the same as not use react document.getElementById(B).scrollTop = target.scrollTop; } 

but actually i want my code to look like

 //what i want <A scrollTop={this.props.scrollSeed}></A> <B scrollTop={this.props.scrollSeed}></B> //... handleScroll(){ this.setState({scrollSeed: ++this.state.scrollSeed}) } 

it is like input

 <input value="this.props.value"/> <input value="this.props.value"/> <input ref='c' onChange={handleChange}> //... handleChange: function() { // enter some code in c and then render in a and b automatically } 

In other words, I need some attribute, for example scrollTop (another form <input value={}> because <A scrollTop={}> does not work), is associated with some state, so I can just use setState and they will be updated on their own.

I have googled before but cannot find answser. I hope that my poor English will not confuse you.

+10
source share
4 answers

There are a number of templates to achieve this. This pattern is what I came up with to lift you up.

First, create a component class that has a large element for the scroll effect. When you drag the scroll bar, this component calls the handleScroll React property to notify its parent component with a 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 top scroll value in its state. Its handleScroll is passed to the child components as a callback. Any scrolling through the children calls a callback, sets the state, leads to redrawing 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 draw the shell, assuming the existing <div id="container"></div> .

 ReactDOM.render( <Wrapper />, document.getElementById('container') ); 
+11
source

this.refs is deprecated. useactjs.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.scrollTop = 0; } render() { return ( <div ref={this.resultsDiv} /> ); } } export default SomeComponent; 
+1
source

Answer 2019

First 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> ) } 

Secondly, a little explanation:

I know why you got here, but I used flex-direction: column-reverse for my FlatList (this is 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 do not need it in my case.

An example using React Hooks is also shown, but you can use the older, more traditional way of defining links.

0
source

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

 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
source

All Articles