Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stale data returning when inputs changed #44

Closed
doelgonzo opened this issue Feb 18, 2022 · 4 comments
Closed

Stale data returning when inputs changed #44

doelgonzo opened this issue Feb 18, 2022 · 4 comments

Comments

@doelgonzo
Copy link

I believe I found a bug. When I pass in a value to a useWorker that relies on a param, the result appears to be cached. It's hard to explain... for the following code:

const {result} = useWorker(createExpensiveFetch, someParam)
console.log(someParam, result)

It produces console logs like this...

123, { a: 'Hello World', b: 123 },

Then on change of someParam to be 124, I see:

124, { a: 'Hello World', b: 123 },
124, { a: 'Foo Bar', b: 124 },

Basically, I have a hook that takes a prop that can change, and it takes tome to process the worker data (think a data fetch)... but when the param changes, the result/error values seem to be the ones corresponding to the previous param. I've gotten around it by making sure the value of result.b matches someParam, but this seems like a bug?

@dai-shi
Copy link
Owner

dai-shi commented Feb 18, 2022

While I understand this is somewhat unexpected, this is intentional behavior.
The background is we allow async generators, which means it can get multiple results for one input. So, having loading isn't technically possible. (Maybe "pending for the first result" might be possible. But, another pattern would be the worker waits for two inputs to return one result..)

So, at this moment, what you did is something I expected as a usage, and I'd do the same.

That said, I'm open for discussions.
FYW, in https://github.com/dai-shi/react-suspense-worker, I took the RPC approach for simplicity.

@doelgonzo
Copy link
Author

doelgonzo commented Feb 20, 2022

Perhaps a simple flag in the response would do the trick. For example, how I got around it now is that I pass in a $inputKey value that is related to my input data. For example:

const [key, setKey] = useState(123)
const workerInput = useMemo(() => ({
  $inputKey: key,
  ...otherParams
}, [key, otherParams])

const {result, error} = useWorker(<createWorker>, workerInput)

I make sure the output of the worker returns the same $inputKey in the resulting object. Then I can do this:

const isOutputStale = useMemo(() => workerInput?.$inputKey !== result?.$inputKey, [workerInput, result])

However, it's a pattern I will have to follow on every single use of this hook. If we could somehow use the dependency to flag it as stale because we're returning an old result, it would skip this step pretty easily. Basically adding a isStale flag to the return value of useWorker. This could leverage the commonplace usePrevious hook to determine that the input doesn't match the previous one, and flag it as non-stale when the window.onMessage receives a message associated to that input... Not sure it would work for the async version of it, but it could at least help with that piece of it.

I just suspect that with the hook pattern, it will seem unexpected to be receiving stale results with no indication of them being stale.

@doelgonzo
Copy link
Author

doelgonzo commented Feb 20, 2022

If this is not an option, this behavior should probably be described in the Readme

@dai-shi
Copy link
Owner

dai-shi commented Feb 21, 2022

Yeah, the notion of "stale" only works for RPC style (one request / one response).
While I understand that the RPC style is majority, this library is trying to be more than that.
So, for now, it's intentional and we should note it in README with a use case recipe for isStale.

@dai-shi dai-shi closed this as completed in f5e4b60 Mar 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants