React - Prevent scrolling to top after changing query params - reactjs

In my Gatsby app I have a page that includes a pagination component.
By default, the path is: '/?page=1' and clicking the pagination buttons changes to '/?page=2', '/?page=3' ...
I am "saving" the page number in the path because I want the browser to remember the page number the user was on previously, in case he clicks the go back button of the browser.
The problem with this approach is that every time the path is changed, the page automatically is scrolling to the top, and I do not want it to scroll to the top.
Does anyone know the way to prevent that?

This is the default Gatsby behavior (known as Scroll Restoration). You have exposed the useScrollRestoration hook in order to play with this behavior (and change it accordingly to your specifications). For example:
import { useScrollRestoration } from "gatsby"
import countryList from "../utils/country-list"
export default function PageComponent() {
const ulScrollRestoration = useScrollRestoration(`page-component-ul-list`)
return (
<ul style={{ height: 200, overflow: `auto` }} {...ulScrollRestoration}>
{countryList.map(country => (
<li>{country}</li>
))}
</ul>
)
}
In your case, you should add your element class name.
Related GitHub threads:
https://github.com/gatsbyjs/gatsby/issues/27349
https://github.com/gatsbyjs/gatsby/issues/19480

Related

reactJS adding an event listener to a navbar tile

I am running the current version of reactJS with hooks. I have three code modules in my app: header.js which creates a navbar and exports it to app.js which adds some other objects and exports all of this to index.js.
I am trying to add an event listener to the individual tiles in the navbar so that I can redirect to the appropriate page.
code
var listenerElement = document.getElementById("Tile1");
if (listenerElement !== null) {
listenerElement.addEventListener("click", navbarClicked) ;
console.log(listenerElement);
} else {
console.log("Element with ID=Tile1 not found");
}
<div id="Tile1" className="linkcontainer">Home</div>
/code
However, I cannot find an appropriate place to add the event-listener and the element with ID "Tile1" is never found - perhaps because it hasn't been rendered as yet?
The element in question is only rendered by index.js but I can't add a function after the reactDOM.render block in index.js - I get an error "not a react function"
Any suggestions would be much appreciated :-)
For react, you should use "refs" to link to a specific aspect of the navabar.
But as you are just trying to have something affect the navbar, you should use the "onClick" property for the div or iconButton or similar.
for example in a function component:
function handleClick() {
console.log("clicked");}
<nav> <iconButton onClick={handleClick} > button </iconButton> </nav>
https://reactjs.org/docs/handling-events.html
In react, you don't work with the DOM directly. React makes a copy of the DOM called virtual DOM and then compares them to update the DOM. You should add your event listener using props.
So instead of:
document.getElementById("Tile1").addEventListener("click", navbarClicked);
you should do <div onClick={navbarClicked} id="Tile1" className="linkcontainer">Home</div>

Unable to update the page limit in pagination - React JS?

I am using pagination component from following link, in that I am unable to update pageLimit value based on user selection how many rows will display.
https://scotch.io/tutorials/build-custom-pagination-with-react
https://codesandbox.io/s/competent-river-xneqb
Initially the page limit will be 10. Once the user clicks the button the page limit will be changed to 15. But the paginations page limit is not changing even after updating the component also.
" import Pagination from "./components/Pagination";
class App extends Component {
state = {
pageLimit : 10
};
handlePageLimit = () => {
this.setState({pageLimit : 15})
console.log("pagelimit inside fun",this.state.pageLimit)
}
return (
<div className="d-flex flex-row py-4 align-items-center">
<Pagination
totalRecords={this.state.totalCountries}
pageLimit={this.state.pageLimit}
pageNeighbours={1}
onPageChanged={this.onPageChanged}
/>
<button onClick={this.handlePageLimit}>Click</button>
</div>
);"
Please help me to resolve such that when the button clicks the page limit should be changed to 15.
This guide has so many issues it would be better to just find another ready solution and implement it from scratch. If you want to keep using that you should start here:
Building on Tom Finney's comment, you would need to use componentDidUpdate and then work from there manually updating stuff in your render function:
componentDidUpdate(prevProps) {
if (prevProps.pageLimit !== this.props.pageLimit) {
this.pageLimit = this.props.pageLimit;
this.totalPages = Math.ceil(this.totalRecords / this.pageLimit);
this.gotoPage(1); // If you want to reset to first page on limit change
}
}
Totally not worth the effort.

How to setup React Router <Link> inside a Datatables.net Cell?

I have a datatables table (https://datatables.net) initialized like this:
$('#example').DataTable({
data: data,
columns: [{
title: "Database ID",
data: 'database_id',
render: function (data, type, row) {
return '<NavLink to="/shop">'+ data +'</NavLink>';
}
}]
});
The NavLink that i have in the code is supposed to render a database cell as a clickable link because of React-Router (This whole function is inside a React component), but the link is not rendering when i run the code.
What i ultimately want is the ability to click on a database cell that will take me to another component by routing into a link like "/shop/id" but i am stuck in it for a long time. Help!
I was facing the same issue and below solution is working for me.
You can directly add anchor tag with href to the path where you want to route upon on the click. But, it will reload your application.
To avoid reloading of the application, try below solution.
When you're initializing the columns dynamically, you can add below code for the column where you want to have a link.
fnCreatedCell: (nTd, data) => ReactDOM.render(
<a
onClick={() => handletableclick(data, props)}>
{data}
</a>, nTd)
Add handletableclick() function/method in your file to handle click event and programmatically through history push the path where you want to route upon the click
function handletableclick(data, props) {
props.history.push("/pathToRoute=" + data);
}
Also,in above code to access history from props, you will need to enclose your component with withRouter
like below :
export default withRouter(YourComponentName);

How to navigate to a particular div on the same page in ReactJS?

I have to navigate to a particular div on the same page in React JS application. For example how it is being done in the following website. When one clicks on < NavLink > the UI scrolls and focuses on the particular div and similarly for other Links on this website.
https://reacttraining.com/react-router/web/api/NavLink/strict-bool
Get the offset of the target element and use window.scrollTo to position it either on top of the page or where ever you want. This would work in chrome/latest browsers. You might want to check for other browser compatibility.
let offsetTop = document.getElementById("yourelement").offsetTop;
window.scrollTo({
top: offsetTop-100,
behavior: "smooth"
});
Program is in codepen https://codepen.io/Divine1/pen/zbQVwR
Update
i have added this logic into a online reactjs project editor and it works.
You can see how this code works https://repl.it/#Divine1/QuietHeartyApplicationstack
Check App.js App.css and the live result.
I think that maybe is a better aproach to use useRef hook. on click is almost the same:
const ref = useRef();
// the function when you want to scroll:
() => window.scrollTo({
top: ref.current.offsetTop -100,
behavior: "smooth"
})
// Where you want to go
<div ref={ref} />

Link in Infobox using react-google-maps causes page reload

I'm not able to put a react-router-dom Link inside of a react-google-maps InfoBox without causing a full page reload.
Here's the code for my InfoBox:
import InfoBox from 'react-google-maps/lib/components/addons/InfoBox'
import { Link } from "react-router-dom";
class MyInfoBox extends Component {
...
const options = {
enableEventPropagation:false,
position: new google.maps.LatLng(loc.latitude, loc.longitude)
};
render(){
return (
<InfoBox options={options}>
<Link to={`/location/${loc.id}`}>Go To Location</Link>
</InfoBox>
);
}
}
All Links in my app work correctly, except for this one.
When the "Go To Location" link is clicked, a full-page reload is caused. I've tried to diagnose by following this issue: https://github.com/tomchentw/react-google-maps/issues/258, but I really don't know enough about the react router v4 to find out if the context contains the router object. Changing the value of enableEventPropagation does not change the behavior.
If anyone can help me understand why the Link is causing a page reload, I would really appreciate it.
Thank you in advance!
Try removing onClick prop in <GoogleMap> component and add enableEventPropagation: true to <InfoBox> options.
For me the issue was that <GoogleMap> onClick event was used to remove <InfoBox> when user clicks outside it. But turns out it is called also inside <InfoBox> so basically it was removing <InfoBox> with the <Link> inside it, before handling <Link> click.

Resources