I am trying to implement a custom search functionality and am using the customTextRenderer property to mark the search text. Problem is when the search text is updated the page component is not re rendered so the text layer does not show the highlighting. It looks like the page component is only rerendered when the page number changes. Is there a way to force the re render to show the updated text layer?
I can see that the marking is working because if I switch to another page then I can see the highlighted text on that page.
Below is the code I am using for the customTextRenderer
customTextRenderer={({ str, itemIndex }) =>
(
reactStringReplace(str, this.state.searchText, (match, i) => (
<mark key={i}>{match}</mark>
))
)}
Hello,
to make React component update itself, you need to pass a new function every time it will return a different output.
So, what you can do is
makeCustomTextRenderer => searchText => customTextRenderer
where customTextRenderer is your function, using searchText argument.
Please mind that this will return a new function on each call, and that's also not optimal, so you'd need to use something like lodash.once to cache the functions so that for one searchText there's only one function generated.
I'm closing this issue to give other issues more visibility. If you still need assistance with this matter, please do not hesitate to reply and I'll reopen.
Happy coding!
Hi
I am still not able to make it work. Can you provide example with full code snippet?
Hey there,
check out what I use for highlighting word "ipsum" in my test suite:
https://github.com/wojtekmaj/react-pdf/blob/master/test/Test.jsx#L126-L133
Maybe that will help you.
CustomRenderer is working if we pass values beforehand, but reading from the state doesn't work. Like i have some values in the UI, which when clicked should be highlighted which i am not able to make it to work. Can you just show full example of how to pass a new function every time like you mentioned above?
Please see: https://github.com/wojtekmaj/react-pdf/wiki/Recipes#highlight-text-on-the-page
As I wrote, it'd be good to use some memoization so that you wouldn't return a new function even if you pass the same searchText.
Hello,
I've run into the same issue and it seems the solution in your recipe alone doesn't do the trick: Even when creating a new function on every search term change, the highlighting doesn't update.
I think the issue can be solved by changing TextLayerItem from a PureComponent to a regular Component. customTextRenderer is passed down from Page to TextLayerItem via the context API and the PureComponent is blocking the re-render when there are just context changes and no prop or state changes.
I think this problem exists with the legacy context API only, so another solution could be switching to the new context API.
PS: A quick and dirty workaround that doesn't need any code changes in the library is to pass down the search term as key prop to the Page component. This re-creates the whole Page component every time the search term changes (however, as it's re-creating and not just updating the component this is not a good solution performance wise).
Thanks wojtekmaj for your example! The search text in the state now correctly updates the marking in the text layer.
However, I am having an issue with the aligning of the text layer when changing the scale of the page. Seems like anything 100% and under correctly lines up, but once you increase the scale over 100% the text layer starts to become misaligned.
Most helpful comment
Hello,
I've run into the same issue and it seems the solution in your recipe alone doesn't do the trick: Even when creating a new function on every search term change, the highlighting doesn't update.
I think the issue can be solved by changing
TextLayerItemfrom a PureComponent to a regular Component.customTextRendereris passed down fromPagetoTextLayerItemvia the context API and the PureComponent is blocking the re-render when there are just context changes and no prop or state changes.I think this problem exists with the legacy context API only, so another solution could be switching to the new context API.