Skip to content

Conversation

@Pnlvfx
Copy link
Contributor

@Pnlvfx Pnlvfx commented Feb 20, 2025

Description

This change updates the type definition for SearchBarProps to accept a ref that can be undefined. Previously, the ref was forced to be non-nullable, which required developers to use workarounds (like non-null assertions) even though React handles null/undefined refs gracefully. With React 19, the framework ensures that refs are managed correctly regardless of their empty initial state.

By allowing n undefined ref, we align the type definitions with React's natural behavior and improve the developer experience by eliminating unnecessary TypeScript errors. This change has no runtime impact, as the component lifecycle guarantees that the ref will be properly set before it is used.

Example that trigger the Typescript Error below:

const searchBarRef = useRef<SearchBarCommands>(undefined);

useLayoutEffect(() => {
  navigation.setOptions({
    headerSearchBarOptions: {
      tintColor: colors.text,
      ref: searchBarRef,
    } satisfies SearchBarProps,
  });
}, [navigation, colors.text]);

Type 'RefObject<SearchBarCommands | undefined>' is not assignable to type 'RefObject'.
Type 'SearchBarCommands | undefined' is not assignable to type 'SearchBarCommands'.
Type 'undefined' is not assignable to type 'SearchBarCommands'.ts(2322)

@Pnlvfx
Copy link
Contributor Author

Pnlvfx commented Feb 20, 2025

Description

This change updates the type definition for SearchBarProps to accept a ref that can be undefined. Previously, the ref was forced to be non-nullable, which required developers to use workarounds (like non-null assertions) even though React handles null/undefined refs gracefully. With React 19, the framework ensures that refs are managed correctly regardless of their empty initial state.

By allowing n undefined ref, we align the type definitions with React's natural behavior and improve the developer experience by eliminating unnecessary TypeScript errors. This change has no runtime impact, as the component lifecycle guarantees that the ref will be properly set before it is used.

Example that trigger the Typescript Error below:

const searchBarRef = useRef<SearchBarCommands>(undefined); // or null

useLayoutEffect(() => {
  navigation.setOptions({
    headerSearchBarOptions: {
      tintColor: colors.text,
      ref: searchBarRef,
    } satisfies SearchBarProps,
  });
}, [navigation, colors.text]);

Type 'RefObject<SearchBarCommands | undefined>' is not assignable to type 'RefObject'. Type 'SearchBarCommands | undefined' is not assignable to type 'SearchBarCommands'. Type 'undefined' is not assignable to type 'SearchBarCommands'.ts(2322)

@Pnlvfx
Copy link
Contributor Author

Pnlvfx commented Feb 20, 2025

Test passed successfully.

@kkafar
Copy link
Member

kkafar commented Feb 24, 2025

hey! thanks for the PR. I took a quick glance I'm not convinced of backward compat of your solution with react 18 yet.
I'll try to find some time this week to test this.

@Pnlvfx
Copy link
Contributor Author

Pnlvfx commented Apr 18, 2025

hey! thanks for the PR. I took a quick glance I'm not convinced of backward compat of your solution with react 18 yet. I'll try to find some time this week to test this.

Ehy no problem. Do you want me to do it using null instead of undefined? I usually use undefined with imperative ref as I prefer it, but yes, maybe react 18 doesn't support undefined, but should definetely support null. If you want I can do it, actually all react 19 users will have this issue, and as far as I know the only way to fix it is provide a nullable (initial) value to the ref.

* * `toggleCancelButton` - depending on passed boolean value, hides or shows cancel button (iOS only)
*/
ref?: React.RefObject<SearchBarCommands>;
ref?: React.RefObject<SearchBarCommands | undefined>;

Choose a reason for hiding this comment

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

This should really use React.Ref<SearchBarCommands>, which takes care of all the different shapes of react ref that could be passed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this or mine are both good,the actually used for me is wrong!

kkafar added a commit that referenced this pull request Dec 23, 2025
This is not breaking as it allows for wider gamut of types to be
accepted.

Ideally we should allow for `React.Ref` there, as suggested here:
#2724 (comment),
but it'd require some more internal changes.
kkafar added a commit that referenced this pull request Dec 23, 2025
This is not breaking as it allows for wider gamut of types to be
accepted.

Ideally we should allow for `React.Ref` there, as suggested here:
#2724 (comment),
but it'd require some more internal changes.

Co-authored-by: Simone Gauli <[email protected]>
@kkafar
Copy link
Member

kkafar commented Dec 23, 2025

This will be done here: #3509

Thanks!

@kkafar kkafar closed this Dec 23, 2025
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.

3 participants