react-string-replace icon indicating copy to clipboard operation
react-string-replace copied to clipboard

Is there any way to run the replace on only the first match?

Open jacobedawson opened this issue 5 years ago • 3 comments

Thanks for a very cool function! What I'm trying to do is replace a user selected string in a body of text with a React component (that contains the selected string). The issue I'm running into is that react-string-replace is replacing all instances of a selection, rather than just the first match.

Since I'm targeting user-selected text (via the Selection API), I'm using a RegExp constructor, like so:

const key = uuid(); // generate unique key
const textRegex = new RegExp(`(${window.getSelection().toString()})`); // capture user selection
const updatedText = ReactStringReplace(postText, textRegex, match => {
  return <HighlightSpan text={match} key={key} />; // return React component
});
// other stuff

This works absolutely perfectly if the selected string is unique in the body of text, but if there is another match then I run into a duplicate key error (and also highlight multiple selections when I only want the first).

Since the RegExp constructor doesn't include a 'g' flag, as far as I understand it should only match the first occurrence - but I might be mistaken as to how react-string-replace works! Is it possible to have it run only once, and if so could you please give me a tip on how to achieve this?

Thanks in advance,

Jake

EDIT

Just actually checked the code and realized that the g & i flags are set by default - perhaps I could make a pull request to have the regex flags optional?

jacobedawson avatar Aug 07 '19 22:08 jacobedawson

Hey @jacobedawson, those flags should only be set if you don't supply your own regex, so I don't think that's the issue.

I'd guess you're running into the behavior of str.split. It will split on every match with or without regex flags. Run this in the console to see what I mean:

'hey there\nthis is a new line'.split(/( )/)

split does support a second limit argument which you might be able to use to your advantage here. I'd recommend trying that approach (either without this lib or with a fork) and seeing where you end up.

If you have a way to incorporate this into the lib that would be great too!

iansinnott avatar Aug 08 '19 03:08 iansinnott

Hey @iansinnott thanks man, yeah I dug a bit further and saw that the flags were only set on !isRegExp(match), I've adapted the function in my project as I'm on a deadline but if I have some spare time I'll make a pull request - after a lot of searching your package finally put me on the right track!

Thanks for making FOSS :)

jacobedawson avatar Aug 08 '19 20:08 jacobedawson

I have now created a PR for this change: https://github.com/iansinnott/react-string-replace/pull/91

kieransimkin avatar Feb 23 '24 11:02 kieransimkin