I want to be able to scroll between table components in my React app. I have created a component for a table called FormattedTable which takes in props and displays all the information that I want.
A lot of the tables refer to other tables with clickable text. If you click on a reference to another table and it is not being displayed, I add the table to the display and the app automatically scrolls down to the bottom of the screen where the table has been added. However, if the table is already being displayed, I want the app to scroll to where it is being displayed already.
The clicking on the reference and adding another table all occurs in the FormattedTable.js file.
In my Home.js I have an array of objects called selected and this array contains all the objects that I want to be displayed in tables. I display the tables by mapping through the selected array creating a FormattedTable component on each iteration.
Home.js
<div className="rightColumn" style={{flex: 4}}>
{selected.length > 0 ? selected.map((obj, index) => {
return (
<div style={{width: '60%'}}>
<FormattedTable data={data} selected={selected} obj={obj} index={index} onSelectedChange={setSelected}/>
</div>
)
})
: null}
</div>
Because the FormattedTables are being created dynamically in the Home.js file, I'm not sure how to scroll from one table to another in FormattedTable.js (since there is only 1 file but multiple instances).
Does anyone know how this would be possible to do in the FormattedTable.js file?
What I've tried so far is added a ref to the div that's being dynamically created in Home.js and also passed in a triggerScroll method to the FormattedTable component so that I can trigger the scroll when a reference is clicked on a table. The issue with this though is that it still scrolls to the last element as the value of the ref is (naturally) the last element of the array when the mapping stops.
<div className="rightColumn" style={{flex: 4}}>
{selected.length > 0 ? selected.map((obj, index) => {
return (
<div ref = {scrollRef} style={{width: '60%'}}>
<FormattedTable data={data} selected={selected} obj={obj} index={index} onSelectedChange={setSelected} triggerScroll={scrollToTable}/>
</div>
)
})
: null}
</div>
Fixed myself:
Added an attribute to each object in the selected array called inFocus. The most recently selected object in the array has a value of true for this attribute.
I then added a ternary to setting the ref of the FormattedTable based on the inFocus attribute so only one object will be set as the ref at a time.
FormattedTable.js
//For selecting results
const select = (name) => {
//Deep clone object so that results doesn't change when selected changes
const obj = cloneDeep(data.find(element => element.name === name));
const refObj = data.find(element => element.name === name);
//If object is in the original JSON array
if(typeof refObj !== 'undefined') {
//If object is not in the selected array, add it to selected array
if(selected.find(element => element.name === name) === undefined) {
//Make the new object in focus and remove the focus for all the other objects
obj.inFocus = true;
copy.map((el) => {
if(el.name !== obj.name) {
el.inFocus = false
}
})
handleSelectedChange([...copy, obj]);
}
//Otherwise, set focus to selected object
else {
//Make the selected object in focus and remove the focus for all the other objects
copy.map((el) => {
if(el.name !== obj.name) {
el.inFocus = false
} else {
el.inFocus = true
}
})
handleSelectedChange([...copy]);
}
}
}
return (
<div ref={obj.inFocus ? messagesEndRef : null} style={{display: 'flex', flexDirection: 'row'}}>
...
)