Git Product home page Git Product logo

Comments (4)

bucknermr avatar bucknermr commented on June 2, 2024

Note: The conditions for this bug are really odd, so I'm not sure if what I'm seeing is the whole issue or if there is something else going on. I stumbled this issue when trying to reproduce a different issue I've been seeing with Reusable+React 17: stale values occasionally being returned from the reusable store when using the selector function, but I've been unable to reproduce that issue.

Also wondering if this may be related #123

from reusable.

CarpeNecopinum avatar CarpeNecopinum commented on June 2, 2024

I think I'm running into a similar/same issue right now with react-native:

const useDoubleCounter = createStore(() => {
    const [counterA, setCounterA] = React.useState({ value: 0 })
    const [counterB, setCounterB] = React.useState({ value: 0 })

    const increment = () => {
        const incremented = { value: counterA.value + 1 }
        console.debug("Incrementing to " + incremented.value)
        setCounterA(incremented)
        setCounterB(incremented)
    }

    console.debug({ counterA, counterB })

    return {
        counterA,
        counterB,
        increment
    }
})

const CounterView = () => {
    const { counterA, counterB, increment } = useDoubleCounter()

    return <View style={{ flexDirection: "column", alignItems: "center", flex: 1, justifyContent: "space-evenly" }}>
        <Text>{counterA.value}</Text>
        <Text>{counterB.value}</Text>
        <Button title="Increment" onPress={increment} />
    </View>
}

When I push the button, the two console.debugs print out the correct incremented value, but the result from the useDoubleCounter()-hook always laggs behind one increment (e.g. pushing the first time prints out "Incrementing to 1", but the Text-elements will continue to show a "0").

Not wrapping the states in an object makes the issue disappear for some reason.

Trying to update the states multiple times inside the increment handler with the same value (both using the same object, or a newly created object with the same value) does not hide the issue.

Involved versions of react/reusable:

from reusable.

CarpeNecopinum avatar CarpeNecopinum commented on June 2, 2024

So one thing I noticed looking at the source code:

At https://github.com/reusablejs/reusable/blob/master/src/react-reusable.tsx#L81

const [localCopy, setLocalCopy] = useState<SelectorValue>(() => selector(store.getCachedValue()));

  useEffect(() => {
    return store.subscribe((newValue) => {
      const selectedNewValue = selector(newValue);

      if (!areEqual(selectedNewValue, localCopy)) {
        setLocalCopy(() => selectedNewValue);
      }
    });
  }, [store, localCopy, selector, areEqual]);

As useEffects are run after the render step, there is a chance of "losing" a notification between the initial state of localCopy and the store.subscribe becoming active.

Updating the subscribe method to force an explicit update (that may be redundant, but should be caught by areEqual) fixes both, my minimal example from above and a more contrived example that is part of a bigger project I'm working on:

  subscribe(callback: StoreValueChangeCallback<HookValue>) {
    this.subscribers = [...this.subscribers, callback];
    if (this.cachedValue != null) callback(this.getCachedValue())
    return () => {
      this.subscribers = this.subscribers.filter(sub => sub !== callback)
    }
  }

If desired, I can turn this into a PR

from reusable.

CarpeNecopinum avatar CarpeNecopinum commented on June 2, 2024

I also tested that fix against @bucknermr's Sandbox and it appears to solve the issue they're having, too.

from reusable.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.