I solved my own problem already but I have no clue as to what’s happening and why it works.
I have a Link
component that links to the same page it’s currently on, but for a different product. So the same component but displaying a different product.
<Link to={directUrl} onClick={() => this.forceUpdate} state={{ urlPicture: picture }}>
Do note <Link>
is in a sub-component, not the main component it routes to itself.
Because it routes to the same page, Link
doesn’t automatically refresh the page. To solve this I added onClick={() => this.forceUpdate}
, but now my state didn’t pass properly. I checked this with the following lines of code in the other component.
location = useLocation()
const [ firstImage, setFirstImage ] = useState(location.state?.urlPicture || null)
console.log(`here is ${mainPicture}`) //mainPicture is just a string
However, when I replace onClick={() => this.forceUpdate}
with onClick={() => window.location.reload()}
, then my state does pass properly through the Link
.
I do know that there is a difference between the 2 and that this.forceUpdate
is the lighter of the 2, but to my knowledge it should refresh the component and update its state. I don’t see why it’s not sufficient and honestly I have no clue why it’s working the way it does.
2
Answers
As said, Link resides in a sub-component, not the main component it routes to itself. When
this.forceUpdate
is called,this
is referring to the sub component and only that will get "force updated". The component with 'firstImage' won't get refreshed.forceUpdate is a function, so it needs to be called in order to have any effect.
Won’t work:
Should work:
or
This is why your
onClick={() => window.location.reload()}
code does actually work, though it reloads the entire app which is very likely unwanted behavior.This said, in almost 100% of the cases if you are reaching out for
forceUpdate
to force trigger a component to rerender you are doing something incorrectly. TheLink
likely is rerendering the component, but the component doesn’t appear to be "reacting" to the route state change. The component being passed the route state should handle it within the React component lifecycle. In this case it would be the use of theReact.useEffect
hook to re-synchronize the local component state with the passed route state.Example:
It is, however, generally considered a bit of a React anti-pattern to store passed state/props/etc into local state. Use these values directly in the component, memoizing them if necessary.
Examples:
In fact, just about any time you have coded a
useState
–useEffect
coupling you should really just use theuseMemo
hook.