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

Couldn't use match index (replace function second arg) as a key #18

Open
kadmil opened this issue May 14, 2017 · 4 comments
Open

Couldn't use match index (replace function second arg) as a key #18

kadmil opened this issue May 14, 2017 · 4 comments

Comments

@kadmil
Copy link

kadmil commented May 14, 2017

Hello! First of all, thanks for the nicest replacer for react. )))

There's a thing. I want to use index parameter in replacer function as a key for react to be happy and render all my replaced texts. If I do two replaces at a time, say

const firstStepTexts = reactStringReplace(myText, regex1, (match, i) => <span key={`first_${i}`}>{match}</span>)
const second = reactStringReplace(firstStepTexts, regex2, (match, i) => <span key={`second_${i}`}>{match}</span>)

Then, for initial string in pattern of ${match_second_regex_1} ${match_first_regex} ${match_second_regex_2} replacer would set the same key for both second regex matches, and then react would blow up swallowing the second match span entirely.

What I did for now was embedding offset param from the new lib version, but that's not the real solution obviously.

What I could do right now is to call .reduce with running total index and not calling reactStringReplace on array, but that way I'm missing perfect lib api use-case. From the api point of lib, I could think of two possible things: 1) having second argument for replace function be running index, and not exact string match index; or 2) having another one argument with that index for replacer function.

First option would almost definitely break someone's workflow (https://xkcd.com/1172/), second one makes api clunky (arghhh, fourth parameter).

What's your opinion on this? I would be happy to help with code, but messing with api without your decision feels not a way to go.

@iansinnott
Copy link
Owner

Hey @kadmil thanks for opening the issue. Hm, I'm still not clear on what causes duplicate keys. If you are using first_${i} and second_${i} when are they duplicated? I thought prefixing like you did would solve the problem

@kadmil
Copy link
Author

kadmil commented May 16, 2017

Unfortunately, prefixing doesn't solve this. What happens here is: replacer for the first regex divides original string to an array like
const firstStepTexts = [textBeforeFirstMatch, {firstRegexMatch}, textAfterFirstMatch]

If I run reactStringReplace on this array, I'd get something like this:

[[ someString, 
   <span key='second_0'>{matchFrom_textBeforeFirstMatch}</span>, 
   someOtherString
 ],

 <span>{firstRegexMatch}</span>,

 [ someString, 
   <span key='second_0'>{matchFrom_textAfterFirstMatch_0}</span>, 
   someOtherString, 
   <span key='second_1'>{matchFrom_textAfterFirstMatch_1}</span>,
   someAnotherString
 ],
]

Note two repeating keys second_0. I was very surprised to learn that react would omit rendering span with matchFrom_textAfterFirstMatch_0 text, because it has repeating key in the same array, although it has another items between them.

As I said, my actual workarounds are at least cumbersome.

@Coriou
Copy link

Coriou commented Apr 20, 2019

Very handy lib, thanks !

I'm having the same issue with duplicate keys being produced. I've created a minimal Codesandox demonstrating the issue: https://codesandbox.io/s/5p570pnwx

@iansinnott
Copy link
Owner

Hm... we could provide a unique key prop to the iterating function so that the calling code doesn't have to worry about it. Like:

const firstStepTexts = reactStringReplace(myText, regex1, (match, i, _, key) => <span key={key}>{match}</span>)

That would stop react from complaining, but it would also not do what keys are supposed to do which is remain consistent from render to render (provide a "stable identity" as the react docs say) so it feels like a duck tape solution to me.

I like the idea of having a "running" or "total" index for every time the replacement function is called, as suggested by @kadmil (sorry forgot to respond before!) but I'm not sure where that index would come from, we could keep track of an index internally but it's not clear to me how that would provide a stable identity to the rendered items, so we might have the same problem as above where it just gets react to be quiet but doesn't provide the real benefit of using keys.

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

No branches or pull requests

3 participants