在组件重新渲染时重置滚动位置

Posted

技术标签:

【中文标题】在组件重新渲染时重置滚动位置【英文标题】:Reset scroll position on component re-render 【发布时间】:2018-04-27 01:31:23 【问题描述】:

看看这支笔:https://codepen.io/segmentationfaulter/pen/XzgJyV

为方便起见,我也在此处粘贴代码。打开上面的笔后,您会看到渲染了一个滑块。向右滚动滑块,点击change slides按钮,你会看到滑块重新渲染了不同的数字,但滑块的滚动位置没有重置。为什么滚动位置没有重置?谢谢

function SliderElement(
  elementContent
) 
  return ( <
    div className = 'slider-element' > 
      elementContent
     < /div>
  )


class Slider extends React.Component 
    render() 
        return ( <
          div className = 'slider' > 
            this.props.sliderContentArray.map(elementContent => < SliderElement elementContent = 
                elementContent
              
              />) <
              /div>
            )
          
        

        class SliderContainer extends React.Component 
          constructor() 
            super()
            this.slidersContent = [
              [1, 2, 3, 4, 5, 6, 7, 8],
              [9, 10, 11, 12, 13, 14, 15, 16]
            ]

            this.state = 
              currentSliderIndex: 0
            
          
          switchSlider() 
            this.setState((prevState) => 
              if (prevState.currentSliderIndex === 0) 
                return 
                  currentSliderIndex: 1
                
               else 
                return 
                  currentSliderIndex: 0
                
              
            )
          
          render() 
            return ( <
              div >
              <
              Slider sliderContentArray = 
                this.slidersContent[this.state.currentSliderIndex]
              
              /> <
              button className = 'slider-switch-button'
              onClick = 
                this.switchSlider.bind(this)
               >
              change slides <
              /button> <
              /div>
            )
          
        

        ReactDOM.render( <
          SliderContainer / > ,
          document.getElementById('root')
        );
.slider 
  display: flex;
  overflow: scroll;


.slider-element 
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 20%;
  height: 100px;
  background: yellow;


.slider-element+.slider-element 
  margin-left: 10px;


.slider-switch-button 
  margin-top: 10px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【问题讨论】:

Scroll to the top of the page after render in react.js的可能重复 【参考方案1】:

您可以针对该问题使用通用解决方案

export const history = createHistory()

history.listen((location, action) => 
    window.scrollTo(0, 0)
)

有了这个监听器,你可以“观察”路由中的每一个变化

来源:https://medium.com/@nasir/reset-scroll-position-on-change-of-routes-react-a0bd23093dfe#

【讨论】:

【参考方案2】:

您的滑块内容重新呈现,但滚动条不知道。对于具有overflow: scroll 属性的div,您需要手动将scrollLeft 位置更改为0,在您的情况下为div with slider className

你可以给它附加一个引用并设置scrollLeft = 0喜欢

class Slider extends React.Component 
  render () 
    return (
      <div ref=this.props.innerRef className='slider'>
        this.props.sliderContentArray.map(elementContent => <SliderElement elementContent=elementContent />)
      </div>
    )
  


class SliderContainer extends React.Component 
  constructor () 
    super()
    this.slidersContent = [
      [1, 2, 3, 4, 5, 6, 7, 8],
      [9, 10, 11, 12, 13, 14, 15, 16]
    ]

    this.state = 
      currentSliderIndex: 0
    
  
  switchSlider () 
    this.setState((prevState) => 
      if (prevState.currentSliderIndex === 0) 
        return  currentSliderIndex: 1 
       else 
        return  currentSliderIndex: 0 
      
    , () => this.slider.scrollLeft = 0)
  
  render () 
    return (
      <div>
        <Slider innerRef=(ref) => this.slider = ref sliderContentArray=this.slidersContent[this.state.currentSliderIndex] />
        <button
          className='slider-switch-button'
          onClick=this.switchSlider.bind(this)
        >
          change slides
        </button>
      </div>
    )
  

CodePen

【讨论】:

【参考方案3】:

每次更新组件时,您都需要使用scrollLeft 属性手动更新滚动位置。您可以在Slider 组件的componentDidUpdate 中执行此操作:

  componentDidUpdate() 
    ReactDOM.findDOMNode(this).scrollLeft = 0;
  

在这里找到工作笔:https://codepen.io/danegit/pen/xPrayY?editors=0010

【讨论】:

以上是关于在组件重新渲染时重置滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 Gatsby JS Link 组件保留滚动位置而不重置到顶部

React 状态在重新渲染后重置

Redux dispatch 导致组件本地状态重置

防止多步 Formik 表单在重新渲染上一步时重置表单控件输入

SwiftUI - 防止列表在项目选择时将滚动位置重置为顶部

wrapRootElement + contextAPI :页面更改导致提供者重新渲染,因此重置状态