Skip to content

Conversation

@onx2
Copy link

@onx2 onx2 commented Nov 23, 2025

Closes

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

Comment on lines +59 to 61
if (substring.length === 0 || string.length < substring.length) {
return true;
}
Copy link
Author

Choose a reason for hiding this comment

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

Maybe also a fast path using indexOf?

Suggested change
if (substring.length === 0 || string.length < substring.length) {
return true;
}
if (substring.length === 0 || string.length < substring.length) {
return true;
}
if (string.indexOf(substring) !== -1) {
return true;
}

snowystinger
snowystinger previously approved these changes Dec 17, 2025
Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

This seems like a fine optimisation. So that we know, are you running into an issue where this is slow? or it just something you noticed? or what caused you to propose the optimisation?

Edit: I read it too fast, this is going to return true for the longer substring, which I think is the opposite of what we want

@snowystinger snowystinger marked this pull request as ready for review December 17, 2025 02:28
@snowystinger snowystinger dismissed their stale review December 17, 2025 02:30

Noticed code is opposite to expectation

@snowystinger
Copy link
Member

Actually, did some more reading on normalize, two un-normalized strings can be different lengths but still be equal, so I don't think we can do this fast path at all
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize In the example you could think of name2 being the substring, but if you just check the length, it's longer than string we're looking for.

Thanks for the thoughts, we can open an issue for more discussion if you don't mind still answering

So that we know, are you running into an issue where this is slow? or it just something you noticed? or what caused you to propose the optimisation?

@onx2
Copy link
Author

onx2 commented Dec 17, 2025

This seems like a fine optimisation. So that we know, are you running into an issue where this is slow? or it just something you noticed? or what caused you to propose the optimisation?

Edit: I read it too fast, this is going to return true for the longer substring, which I think is the opposite of what we want

I wasn't running into any specific issue with it, I just noticed that it might be an optimization while implementing an fuzzyContains extension of the useFilter hook. If you found that it would cause false positives then I wouldn't advocate for it 😄

export function useFilter(options: FilterOptions = {}): Filter {
  const { threshold = 2, maxLength = 256, sensitivity = "base", ...collatorOptions } = options;
  const ariaOpts = { sensitivity, ...collatorOptions };

  const filter = useFilterAria(ariaOpts);
  const collator = useCollator(ariaOpts);

  const normalize = useMemo(
    () => (str: string) => normalizeForCollation(str, sensitivity, collator),
    [collator, sensitivity]
  );

  const fuzzyContains = useCallback(
    (text: string, query: string): boolean => {
      if (!query) return true;
      if (!text) return false;

      if (text.length > maxLength || query.length > maxLength) return false;

      if (filter.contains(text, query)) return true;

      if (Math.abs(text.length - query.length) > threshold) return false;

      const textNorm = normalize(text);
      const queryNorm = normalize(query);

      if (textNorm === queryNorm) return true;

      if (Math.abs(textNorm.length - queryNorm.length) > threshold) return false;

      return distance(textNorm, queryNorm) <= threshold;
    },
    [filter.contains, normalize, threshold, maxLength]
  );

  return {
    ...filter,
    fuzzyContains,
  };
}

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.

2 participants