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

Forward unused props in ReanimatedSwipeable and Pressable to their inner components #3039

Merged
merged 19 commits into from
Aug 20, 2024

Conversation

latekvo
Copy link
Contributor

@latekvo latekvo commented Aug 9, 2024

Description

Currently large portion of the props accepted by ReanimatedSwipeable and Pressable components remain unused.
This issue mostly refers to all the accessibility props.

This PR adds the use of spread operator to ReanimatedSwipeable and Pressable to forward all the remaining props to inner components, which are not explicitly used otherwise.

Fixes: #3032

Test plan

  • turn on radio description
  • open the nested Pressable example
  • add accessibilityLabel prop to one of the Pressables
  • navigate over the modified Pressable with your keyboard (use Tab and Shift-Tab to navigate)
  • hear as your label is being read out, which wouldn't occur without this change

@latekvo latekvo marked this pull request as ready for review August 9, 2024 10:20
@latekvo
Copy link
Contributor Author

latekvo commented Aug 9, 2024

I just found that using the following code works just as well as the ManagedProps method:

const { children, style, ...rest } = props;

The only downside being that it requires to pull out props before being used, as opposed to accessing them directly from the props object.

And so if we've got 20 unique props in one of our components, that'll require having a 20-line-long header of extracted props as opposed to pulling them on-the-go.

@j-piasecki @m-bert Would we prefer to stick with the ManagedProps method, or remove it in favour of this new one?

@m-bert
Copy link
Contributor

m-bert commented Aug 11, 2024

ManagedProps looks like using a sledgehammer to crack a nut. In my opinion using spread syntax is enough.

And so if we've got 20 unique props in one of our components, that'll require having a 20-line-long header of extracted props as opposed to pulling them on-the-go.

I think that it is unrealistic edge-case that we shouldn't be concerned about.

Also, I have a couple of comments on the code, but first let's see if @j-piasecki agrees with me 😅

Copy link
Member

@j-piasecki j-piasecki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go with spreading the props. It may be verbose, but it's explicit in what it does.

src/components/utils.ts Outdated Show resolved Hide resolved
src/components/utils.ts Outdated Show resolved Hide resolved
src/components/utils.ts Outdated Show resolved Hide resolved
@latekvo
Copy link
Contributor Author

latekvo commented Aug 12, 2024

I think that it is unrealistic edge-case that we shouldn't be concerned about.

i believe it's the exact case this PR is dealing with.
The 2 components utilising ManagedProps are ReanimatedSwipeable and Pressable, both using 16 and 17 unique props respectively.

Although with all that said, I think spread operator approach is indeed simpler and more readable than ManagedProps.


Converted to spread operator approach in 0ee242f.

@m-bert
Copy link
Contributor

m-bert commented Aug 12, 2024

i believe it's the exact case this PR is dealing with.

Oh okay, what I had in mind was only passing props to components, I forgot about the whole implementation dealing with different props. Nevertheless I believe that spread syntax is better 😅

Copy link
Contributor

@m-bert m-bert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update title and description of this PR.

android_ripple,
disabled,
...remainingProps
} = useMemo(() => props, [props]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to use useMemo?

Copy link
Contributor Author

@latekvo latekvo Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, we have some useStates which may cause re-renders independently of props changing.
If we were to remove this useMemo, those props would trigger every useCallback to reload each render as well, making useCallbacks useless.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary, memoization of props passed to the component should be on the user. For example, we cannot correctly memoize event handlers, without knowing what's in their closure (and we don't have access to it).

Adding to that, I don't think it actually does anything here. React uses Object.is to compare the dependencies. You're passing an entire props object as a dependency, which is created anew for every render and objects are compared based on reference, not value.

Copy link
Contributor Author

@latekvo latekvo Aug 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, that makes sense.


I'll remove all the useMemo on props instances, all useCallback instances which depend on any of the props.

Do you think there are any other sensible ways to go about optimising the now non-memoized functions, or should they be left as-is?

I won't remove the ones which compare primitive value props, as these are compared by value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other calls to useCallback and useMemo are fine. I meant specifically this one where you used the entire props object in the dependency array.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a user uses useCallback to memoize event handlers we want to be able to utilize that and make less updates ourselves.

Copy link
Contributor Author

@latekvo latekvo Aug 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I understand, I kept all the other useMemo and useCallback instances as all the values they depend on may be primitive values, sorry for the previous commotion.

Removed prop memoization in cc3ecdc

onSwipeableClose,
testID,
...remainingProps
} = useMemo(() => props, [props]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Copy link
Contributor Author

@latekvo latekvo Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do want to keep this one, as the ForwardedRef prop may change without changing SwipeableProps prop.
While spread in itself doesn't use up too much resources, it will trigger dependency changes for multiple useCallbacks further down the file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

@latekvo latekvo changed the title Add props wrapper to isolate remaining unused props Forward unused props in ReanimatedSwipeable and Pressable Aug 13, 2024
@latekvo latekvo changed the title Forward unused props in ReanimatedSwipeable and Pressable Forward unused props in ReanimatedSwipeable and Pressable to their inner components Aug 13, 2024
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

Successfully merging this pull request may close these issues.

ReanimatedSwipeable > Jest > getByGestureTestId fails to find component.
3 participants