ctrlplusb / react-jobs

Asynchronously resolve data for your components, with support for server side rendering.
MIT License
166 stars 34 forks source link

withJob has workingProps state to ignore an old work's late resolve. #47

Open dehypnosis opened 6 years ago

dehypnosis commented 6 years ago

To solve issue #45 (Need to abort an old work when a new work started).

I made a simple solution.

When new work starts, store the reference of current props object as wokringProps in the component. And when job finished, compare the current props reference (in closure) with the stored wokringProps reference. If references are not equal, just ignore the result as like ignore unmounted component I'd like you to take a look at it.

codecov[bot] commented 6 years ago

Codecov Report

Merging #47 into master will not change coverage. The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master      #47   +/-   ##
=======================================
  Coverage   94.17%   94.17%           
=======================================
  Files           5        5           
  Lines         103      103           
  Branches       31       31           
=======================================
  Hits           97       97           
  Misses          6        6
Impacted Files Coverage Δ
src/withJob.js 91.52% <100%> (ø) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 6f99572...12110e2. Read the comment docs.

ctrlplusb commented 6 years ago

Hey @dehypnosis!

Thanks for this. It's a really interesting case to cover.

I had a quick look and I think in principal it makes sense. One question though - do you think it would be safer to do a shallow equality check on the props object instead? Can we guarantee React always returns the same "wrapping" object holding the props?

What do you think?

I really appreciate the help 👍

dehypnosis commented 6 years ago
resolveWork = (props) => {
  this.setState({ completed: false, data: null, error: null, workingProps: props })

...

if (isPromise(workDefinition)) {
    // Asynchronous result.
       return workDefinition
           .then((data) => {
               if (this.unmounted || this.state.workingProps !== props) {
...

Thank you for the answer. In the submitted code, the comparison this.state.workingProps !== props is performed in the closure, so unless resolveWork called twice, props and workingProps will refer the same object naturally.

Did I rightly recognize your point? As far as i know componentWillReceiveProps invokes only when props !== nextProps