I am trying to create a component where there are two tabs, one is a table that displays data, and the other lets the user view more in depth information on specific entries in the table. The issue I am having is that the component is at the bottom of a page, and the info tab is shorter than the table tab, so when I switch between them it shortens the page and jumps instead of scrolling smoothly.
Is there a way to have the page scroll instead of jumping like this, and if that is impossible, is there at least a way to have it scroll before rendering the change?
I tried using useLayoutEffect to scroll before switching, but it only works when going from the larger table tab to the shorter info tab. This is what I have so far:
import React, { useState, useRef, useLayoutEffect } from "react";
import { Button } from "react-bootstrap";
import '../.css'
export default function Example(props) {
const fields = ["ID", "A count", "B count", "diff"]
const data = [{ id: 1, aCount: "data", bCount: "data", diff: "difference" },
{ id: 2, aCount: "data", bCount: "data", diff: "difference" },
{ id: 3, aCount: "data", bCount: "data", diff: "difference" },
{ id: 4, aCount: "data", bCount: "data", diff: "difference" },
{ id: 5, aCount: "data", bCount: "data", diff: "difference" },
{ id: 6, aCount: "data", bCount: "data", diff: "difference" },
{ id: 7, aCount: "data", bCount: "data", diff: "difference" },
{ id: 8, aCount: "data", bCount: "data", diff: "difference" },
{ id: 9, aCount: "data", bCount: "data", diff: "difference" },]
const [isTableVisible, setIsTableVisible] = useState(true)
const [infoData, setInfoData] = useState(data[0])
const tabRef = useRef()
const isMounted = useRef(false);
useLayoutEffect(() => {
if (isMounted.current) {
tabRef.current.scrollIntoView()
} else {
isMounted.current = true;
}
}, [isTableVisible]);
function handleTabClick() {
setIsTableVisible(!isTableVisible)
}
function handleViewClick(index) {
setIsTableVisible(false)
setInfoData(data[index])
}
return (
<div>
<div className="ref" id="table" ref={tabRef} />
{isTableVisible ?
<div>
<span className="tab-active"> Table </span><span className="tab" onClick={handleTabClick}> Info </span>
</div>
: <div>
<span className="tab" onClick={handleTabClick}> Table </span><span className="tab-active"> Info </span>
</div>}
{isTableVisible ?
<div>
<table className="data-table">
<thead>
<tr>
{fields.map((field, i) => <th key={field}>{field}</th>)}
</tr>
</thead>
<tbody>
{data.map((currData, i) =>
<tr key={i}>
<td>{currData.id}
<br />
<Button
variant="btn btn-outline-primary"
onClick={(e => handleViewClick(i))}>
View
</Button>
</td>
<td>
{currData.aCount}
</td>
<td>
{currData.bCount}
</td>
<td >
{currData.diff}
</td>
</tr>
)}
</tbody>
</table>
</div>
: <div className="info-section">
Box for Data
</div>
}
</div>
)
}
2
Answers
Found a way to scroll up before rendering the change. I wrote a promise to check if the scroll was complete, and only then does the tab switch. this solved the issue I was having. here is the solution:
Well yes, if you use the parameters to specify it…
There’s also the scroll() function with parameters in case you need it…
More detail for options here…
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView