Reputation: 9903
I get a weird error when running my React Native app:
Some sample code:
const { url } = <incoming object>;
const reURL = <my regex>;
console.debug('url:', url);
console.debug('typeof url:', typeof url);
matches = [...url.matchAll(reURL)];
Log output:
url: <as expected>
typeof url: string
Error message:
TypeError: url.matchAll is not a function. (In 'url.matchAll(reURL)', 'url.matchAll' is undefined)
Everything works fine on iOS, the error only occurs on Android.
Pretty up to date environment, updated all npm
packages a couple of days ago.
Does anyone have the slightest idea where to even begin searching for a solution ?
Upvotes: 6
Views: 4224
Reputation: 1791
Replacing the call to str.matchAll(regex)
with the recursive function in this answer did the job perfectly for me.
Pasting here the function with TS support for completeness:
/**
* Recursive function which replaces the usage of `str.matchAll(regex)` which happens to be troublesome on Android once compiled.
* @param regex - regex expression to be executed. If passed with the `/g` global flag the result will return all matches.
* @param str - string value to be searched for matches by the regex expression
* @param matches - parameter used to pass on the current resulting array through recursion iterations
* @returns array of all matches found while executing the regex
*/
export function findAllMatches(regex: RegExp, str: string, matches: RegExpExecArray[] = []) {
const res = regex.exec(str)
res && matches.push(res) && findAllMatches(regex, str, matches)
return matches
}
Ensuring nobody in the codebase would try to use matchAll
again could be achieved by adding the following es-lint
rule:
"no-restricted-syntax": ["error", {
"selector": "CallExpression[callee.property.name='matchAll']",
"message": "You should use the findAllMatches function instead."
}]
Upvotes: 0
Reputation: 69
For us, this issue was solved by conditionally evaluating matchAll:
ourSring.matchAll?.(expr);
Our working theory is that the first time this method is accessed, some native async regex initialization is run, but takes some time to bind the method, resulting in undefined matchAll
method.
Subsequent evaluations work properly for us.
Upvotes: 0
Reputation: 693
You can use string.prototype.matchall
to polyfill.
https://www.npmjs.com/package/string.prototype.matchall
import matchAll from 'string.prototype.matchAll'
matchAll.shim()
Upvotes: 1
Reputation: 49
I have the same issue. String.matchAll
does not work for Android. You should use match
instead matchAll
.
Example:
const regex = new RegExp(text, 'ig');
const arr = string.match(regex);
You will get an array match regex
Upvotes: 1