A part of my app is a huge wall of text, made up of many small paragraphs.
The various text components are wrapped in an IonContent and an IonPage.
At the very top sits a component called ReaderPage.
There are other pages, such as ConfigPage.
In the config page it is possible to change the fontsize. It is stored in a react Context which is consumed by the reader. A config change causes the reader page to re-render and reflows all the text. So far so good
But after changing the fontsize and switching back to the reader, the user now looks at a different section of the text. The scrolling position is not correct.
What I would like to do is: When the fontsize has changed, scroll to the last piece of text that was visible on the screen.
This rescrolling is a one-time action, like an event. It seems really hard to do this in a clean way with React.
For now I’ve found a workaround: Reader and Config share another Context. This Context contains a boolean flag and methods to switch it on and off. Changing the fontsize in the config switches the flag on. In the reader there is a useEffect which checks the flag and if it’s on, it does the rescrolling and switches the flag off.
I think I have most of the pieces in place:
- The config is synced to the reader, changing the fontsize causes a rerender with the new size.
- The visibility of text items is tracked. The currently visible item is registered as “last on screen”.
- When the reader page is on screen, it is possible to scroll to any desired item
- the message passing between config and reader works. I have a useEffect that is only executed after the flag has been switched on.
Now, the problem is:
The scrolling to item xyz is done by taking its offsetTop and then scrolling to that position.
This works when the reader page is currently on screen.
But when the config is changed, it changes a context that is consumed by the reader page. This immediately causes the reader page to rerender. And it also fires off the useEffect immediately. The reader page checks the flag and knows that it should rescroll. But the offsetTop can’t be calculated, since the item is not actually on screen.
When removing the flag check, the reader page scrolls to the desired item after each re-render. And I can see that this works.
But with the flag check, it tries to do the scrolling when it’s not on screen. And that fails.
Do you have an idea on how to fix this?
Can I maybe prevent rendering the routes that are not on-screen?