My instinct is that there might be a missing primitive. On the one hand, if you have something like
const UserComponent = ({userId} /* constructor props */) => {
const data = fetchUserById(userId)
return renderProps => ...
}
then, if the userId changed, then cleaning up that effect (not shown, and most people probably would leak memory everywhere...) and recreating a new user component is exactly what you want!
On the other hand, you might want the signature to be
({ userId } /* initial render props */) => {
let currentlyMountedUserId = userId;
let data = fetchUserById(currentlyMountedUserId);
return ({ userId: newUserId } /* subsequent render props */) => {
if (newUserId != currentlyMountedUserId) {
currentlyMountedUserId = newUserId;
data = fetchUserById(newUserId)
}
// ...
}
}
Anyway, by now, we clearly have a lot of boilerplate. But it still might be the right primitive, if a framework codegenned all of this.
(It's just JavaScript™ is silly, and leaves a lot of DevEx or perf on the table)