I'm using Redux in my app, inside a Component I want to scroll to an specific div tag when a change in the store happens. I have the Redux part working so it triggers the ponentDidUpdate() method (I routed to this poennt view already). The problem as far as I can tell, is that the method scrollIntoView() doesn't work properly cos ponentDidUpdate() has a default behavior that scrolls to the top overwriting the scrollIntoView(). To work-around it I wrapped the function calling scrollIntoView() in a setTimeout to ensure that happens afeterwards. What I would like to do is to call a preventDefault() or any other more elegant solution but I can't find where to get the event triggering the 'scrollTop' I looked through the Doc here: .html#ponentdidupdate and the params passed in this function are ponentDidUpdate(prevProps, prevState) ,since there is no event I don't know how to call preventDefault()
I've followd this Docs: .html And tried different approaches people suggested here: How can I scroll a div to be visible in ReactJS?
Nothing worked though Here is my code if anyone has any tip for me, thanks
class PhotoContainer extends React.Component {
ponentDidUpdate(){
setTimeout(() => {
this.focusDiv();
}, 500);
}
focusDiv(){
var scrolling = this.theDiv;
scrolling.scrollIntoView();
}
render() {
const totalList = [];
for(let i = 0; i < 300; i += 1) {
totalList.push(
<div key={i}>{`hello ${i}`}</div>
);
}
return (
<div >
{totalList}
<div ref={(el) => this.theDiv = el}>this is the div I'm trying to scroll to</div>
</div>
)
}; }
I'm using Redux in my app, inside a Component I want to scroll to an specific div tag when a change in the store happens. I have the Redux part working so it triggers the ponentDidUpdate() method (I routed to this poennt view already). The problem as far as I can tell, is that the method scrollIntoView() doesn't work properly cos ponentDidUpdate() has a default behavior that scrolls to the top overwriting the scrollIntoView(). To work-around it I wrapped the function calling scrollIntoView() in a setTimeout to ensure that happens afeterwards. What I would like to do is to call a preventDefault() or any other more elegant solution but I can't find where to get the event triggering the 'scrollTop' I looked through the Doc here: https://facebook.github.io/react/docs/react-ponent.html#ponentdidupdate and the params passed in this function are ponentDidUpdate(prevProps, prevState) ,since there is no event I don't know how to call preventDefault()
I've followd this Docs: https://facebook.github.io/react/docs/refs-and-the-dom.html And tried different approaches people suggested here: How can I scroll a div to be visible in ReactJS?
Nothing worked though Here is my code if anyone has any tip for me, thanks
class PhotoContainer extends React.Component {
ponentDidUpdate(){
setTimeout(() => {
this.focusDiv();
}, 500);
}
focusDiv(){
var scrolling = this.theDiv;
scrolling.scrollIntoView();
}
render() {
const totalList = [];
for(let i = 0; i < 300; i += 1) {
totalList.push(
<div key={i}>{`hello ${i}`}</div>
);
}
return (
<div >
{totalList}
<div ref={(el) => this.theDiv = el}>this is the div I'm trying to scroll to</div>
</div>
)
}; }
if(input){ this.textInput = input; }
, but I suspect this isn't your problem. I've just tried to run your code, and it appears to work in my case. I had to include ponentDidMount() however as I was not manipulating state anywhere in my ponent (ponentDidUpdate() is only called if the ponent state is changed). I also removed the bootstrap CSS classes. See here: github./finbarrobrien/reacty/blob/master/src/App.js
– Finbarr O'B
Commented
Jul 13, 2017 at 11:30
Ok it's been a while but I got it working in another project without the setTimeOut
function so I wanted to answer this question.
Since Redux pass the new updates through props, I used the ponentWillRecieveProps()
method instead of ponentDidUpdate()
, this allowes you a better control over the updated properties and works as expected with the scrollIntoView()
function.
class PhotoContainer extends React.Component {
ponentWillReceiveProps(newProps) {
if (
this.props.navigation.sectionSelected !==
newProps.navigation.sectionSelected &&
newProps.navigation.sectionSelected !== ""
) {
this.focusDiv(newProps.navigation.sectionSelected);
}
}
focusDiv(section){
var scrolling = this[section]; //section would be 'theDiv' in this example
scrolling.scrollIntoView({ block: "start", behavior: "smooth" });//corrected typo
}
render() {
const totalList = [];
for(let i = 0; i < 300; i += 1) {
totalList.push(
<div key={i}>{`hello ${i}`}</div>
);
}
return (
<div >
{totalList}
<div ref={(el) => this.theDiv = el}>
this is the div I am trying to scroll to
</div>
</div>
)
};
}
I also struggled with scrolling to the bottom of a list in react that's responding to a change in a redux store and I happened upon this and a few other stackoverflow articles related to scrolling. In case you also land on this question as well there are a few ways this could be a problem. My scenario was that I wanted a 'loading' spinner screen while the list was rendering. Here are a few wrong ways to do this:
{loading ?
<Spinner />
:
<List />
}
as stated above this doesn't work because the list you might want to scroll to the bottom of isn't rendered yet.
<div style={{display: loading ? 'block' : 'none'>
<Spinner />
</div>
<div style={{display: loading ? 'none' : 'block'>
<List />
</div>
This doesn't work either since the list you want to scroll to the bottom of isn't actually being displayed likely when you call the scroll.
The better approach for the above scenario is to use a loading that acts as an overlay to the ponent. This way both the spinner and list are rendered and displayed, the scroll happens, and when the loading is plete, the spinner can be de-rendered or set to be invisible.