T
TanStack2mo ago
flat-fuchsia

The component rerender whole application every time when I switch between items in the list on hover

This issue occurs due to the to parameter. Should I comment it out or use a static value? What’s the best approach for this code? <WrapperComponent {...(hasChildren ? { onClick: handleToggleCollapse, className: cn('flex-1', 'cursor-pointer w-full', !isSystemView && 'overflow-hidden'), } : { to: navParams.url, params: navParams.params, search: navParams.search, className: cn('flex-1', 'cursor-pointer w-full', !isSystemView && 'overflow-hidden'), } )} /> const WrapperComponent = hasChildren ? 'div' : Link;
13 Replies
fascinating-indigo
fascinating-indigo2mo ago
unclear what this is
flat-fuchsia
flat-fuchsiaOP2mo ago
I have a list component where each item is wrapped in a Link component. The Link uses a dynamic to prop that gets recreated on every render:
<Link
to={buildUrl(id, 'default', organizationId).url} // Dynamic
params={navParams.params}
search={navParams.search}
>
{item.name}
</Link>
<Link
to={buildUrl(id, 'default', organizationId).url} // Dynamic
params={navParams.params}
search={navParams.search}
>
{item.name}
</Link>
The problem: Whenever I hover over any item in the list, it causes the entire page to re-render. When I remove the to prop entirely, the re-rendering stops and everything works fine. My options: 1. Remove the to prop (but this gives TypeScript errors) 2. Use a static to prop like to="/app/$organizationId/inbox/$ticket_number" 3. Something else? What's the recommended approach for this scenario? Should I use a static to with dynamic params, or is there a better pattern? this is the type of wrapper component const WrapperComponent = hasChildren ? 'div' : Link;
fascinating-indigo
fascinating-indigo2mo ago
looks like you need to useMemo this thing? i cant explain the rerendering, a full reproducer project might help is buildUrl typesafe btw?
flat-fuchsia
flat-fuchsiaOP2mo ago
i tried memoization for this buildURL funnction but seems not working this is buildURL function const buildUrl = (id: string, latestTicketNumber: string, organizationId: string) => { // Get the current view type from the store to preserve user preference const { viewType } = useInboxState.getState() const url = /app/$organizationId/inbox/$ticket_number const params = { organizationId: organizationId, ticket_number: latestTicketNumber, } const search: { view: string; subview?: string; type: 'list' | 'regular' } = { view: id, subview: undefined, type: viewType, // Use stored view type preference } return { url, params, search, } } only
to : "."
to : "."
is fixing render issue rn. but i don't understand the reason behind it
fascinating-indigo
fascinating-indigo2mo ago
as written above, a full reproducer is needed btw if you only need to change search, then sure to:"." is the way to go
flat-fuchsia
flat-fuchsiaOP2mo ago
This is the issue
fascinating-indigo
fascinating-indigo2mo ago
i wont debug a screencapture, sorry
flat-fuchsia
flat-fuchsiaOP2mo ago
code is confidential. i can't share 😭 . but still is there any reason why this to:"." something but to: /app/$organizationId/inbox/$ticket_number, throw type error
fascinating-indigo
fascinating-indigo2mo ago
i cant follow you dont need to share your code you should share a minimal reproducer
flat-fuchsia
flat-fuchsiaOP2mo ago
here's the minimal procedure
const MyComponent = () => {
const [isHovered, setIsHovered] = useState(false)

const navParams = buildUrl(id, 'default', organizationId)

return (
<div onMouseEnter={() => setIsHovered(true)}>
<Link
to={navParams.url}
params={navParams.params}
search={navParams.search}
>
Click me
</Link>
</div>
)
}

const buildUrl = (id, ticket, orgId) => {
const { viewType } = useInboxState.getState()
return {
url: `/app/$organizationId/inbox/$ticket_number`,
params: { organizationId: orgId, ticket_number: ticket },
search: { view: id, type: viewType }
}
}
const MyComponent = () => {
const [isHovered, setIsHovered] = useState(false)

const navParams = buildUrl(id, 'default', organizationId)

return (
<div onMouseEnter={() => setIsHovered(true)}>
<Link
to={navParams.url}
params={navParams.params}
search={navParams.search}
>
Click me
</Link>
</div>
)
}

const buildUrl = (id, ticket, orgId) => {
const { viewType } = useInboxState.getState()
return {
url: `/app/$organizationId/inbox/$ticket_number`,
params: { organizationId: orgId, ticket_number: ticket },
search: { view: id, type: viewType }
}
}
fascinating-indigo
fascinating-indigo2mo ago
thats unfortunately not a reproducer. please fork one of routers stackblitz examples, change it so it reproduces the issue and then paste the link here
flat-fuchsia
flat-fuchsiaOP2mo ago
okk thanks
fascinating-indigo
fascinating-indigo2mo ago

Did you find this page helpful?