Skip to content

Possible race condition with useSelector #1508

Closed
@markerikson

Description

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

This was reported by @Jessidhia over in Reactiflux, so I'll paste her writeup:

Jessidhia : hmm, no, there is definitely some spooky race condition in react-redux
Jessidhia : likely in how it uses Refs
Jessidhia : this is the state of a useSelector that is returning null:

{
  name: 'Selector',
  subHooks: [    {
      name: 'ReduxContext',
    },
    {
      name: 'SelectorWithStoreAndSubscription',
      subHooks: [        { id: 0, isStateEditable: true, name: 'Reducer', value: 0 },
        {
          id: 1,
          isStateEditable: false,
          name: 'Memo',
          value: {
            ...Subscription
          }
        },
        { id: 2, name: 'Ref', value: undefined },
        {
          id: 3,
          name: 'Ref',
          value: root => cachedUserWorksAllByType(root, userId, WorkType.Illust)[index]
        },
        {
          id: 4,
          name: 'Ref',
          value: {
            illustId: '78095873',
            illustTitle: '?????',
            ...moreDataThatIsNotNull
          }
        },
        { id: 5, name: 'LayoutEffect' },
        { id: 6, name: 'LayoutEffect' }
      ]
    }
  ]
}

Note how the update counter (Reducer) is still at 0 and the value cached in the third Ref is most definitely not null
Jessidhia : it is possible for that selector (cached in the second Ref) to return null, but never after it has already returned an object. undefined -> (object) or undefined -> null -> (object) are the only possible transitions.
Jessidhia : I have no idea how to reduce this or make it reproducible, though
Jessidhia : it's very finicky
Jessidhia : some instances of the component (that do transition null -> object) get the counter incremented to 3, others do call the refEquality function (which I'm spying on) and the counter doesn't get incremented at all despite it returning false
Jessidhia : but since the Ref was updated, unless changes to props or a parent update triggers a rerender of the component, redux updates alone won't cause updates

Jessidhia: what do you think of https://gist.github.com/Jessidhia/afac05ee884c34d588547324ba0d49ec ? I believe this avoids the race condition I'm encountering, though I have no idea how to prove that.

What is the expected behavior?

Presumably that whatever race condition here doesn't happen.

Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using? Which browser and OS are affected by this issue? Did this work in previous versions of React Redux?

I assume React-Redux v7.1.x.

Note that this overlaps with the refactoring we're doing in #1506 , and we should look at the gist to see what changes are there and if we can apply them. I'd also like to figure out if we can replicate the problem being seen, prior to applying the memory leak changes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions