Search code examples
javascriptreactjsreduxisomorphic-javascript

React/Redux - Scrolling a div after page has been server-side rendered


I have an application which uses server side rendering in React and Redux.

In the application there is a Grid of information which is wrapped inside a div tag. I have attached to it a 'ref' attribute in order to manipulate the scrollbar of that particular div.

  render(){
    this.gridPosition()
    return (
      <div className='m_wrap' ref="scrollbars">
        <TimeBar/>
        <ChannelInfo info={this.props} />
      </div>
    )
  }

And gridPosition is:

  gridPosition(){
    if (this.props.slidePos == "Morning"){
      this.refs.scrollbars.scrollLeft = 0;
    } else if (this.props.slidePos == "Afternoon") {
      this.refs.scrollbars.scrollLeft = 2880;
    } else if (this.props.slidePos == "Evening") {
      this.refs.scrollbars.scrollLeft = 5280;
    } else if (this.props.slidePos == "Night") {
      this.refs.scrollbars.scrollLeft = 7200;
    }
  }

So the position of the scrollbar is determined by this.props.slidePos

This works when the application is loaded however it won't set the correct position on the initial render.

I have tried firing off an action in the componentDidMount() function but the div tag doesn't seem to be connected to the application after the server render.

If anyone could shed some light on this or point me in the right direction to resolve it I would be very grateful.


Solution

  • Altering your scroll position inside componentDidMount is the right way to do it. Event when you receive initial html rendered on server-side React will render your app (ReactDOM.render(....) is still here and being called) at client-side and will compare resulting checksums. If they will not match React will replace received DOM with just rendered one.

    Your div.scrollbars will be available in refs by the time of componentDidMount invocation. It will not only in case it was not part of your components hierarchy, i.e. it was not rendered. You can see working example showing scrolling server-rendered content here.

    In general case your first code snipped where you call this.gridPosition() from render function should actually fall with exception, because by the time gridPosition is accessing this.refs.scrollbars it have not been created yet by render method. The only chance this code is working is because first render of your Component happens with the value of this.props.slidePos not matching any of listed in gridPosition.

    Also please not, that using String Refs is deprecated.