React router with regex - inserting a number in middle of the path - reactjs

I get my current path by using useLocation() hook.
I have several buttons and want them to navigate me to the current path combined with that concrete list ID.
Lets suppose its https://localhost:3000/list/3/items
How to insert that ID (here is 3) in between - list/{id}/items - with regex?
const navigate = useNavigate();
const location = useLocation();
// location.pathname - getting current path
// pinned to each button
const handleListChange = (listId: number) => {
// navigate(...);
};
I cant achieve that with just navigate("/list/{listId}/items") because /items can differ depending on what subpage im currently at ("/list" stays the same). So it can be for example list/{listId}/itemsSubpage/.../.... I just want to stay at the current page when navigating and only let id change.

Why not simply redirect starting from the root? I don't see the need for a regular expression here.
navigate(`/list/${listId}/items`);
or am I missing something?
Post Edit answer:
There are a few ways to achieve what you want but I'll just go ahead and post the one that came to me first, you can adjust it to your needs.
const exp = /(\/list\/)\d{1,}(\/?.+)?$/i;
const currentUrlMock = 'https://test.com/list/240/items/subpage/2/doesnt-matter'
const replaceId = (newId) => currentUrlMock.replace(exp, `$1${newId}$2`)
console.log(replaceId(3));
// logs: https://test.com/list/3/items/subpage/2/doesnt-matter
How this works is that the regular expression contains two capture groups:
(\/list\/) that matches the /list part
(\/?.+)?$ that matches everything that appears after your ID
Between them there's a \d{1,} that will capture all digits, it's not a capture group though - it has no parentheses around it ().
Replace method on string accepts regex as a first param and in the second param you can access captured groups by using dollar signs and group number, $1 to capture first group, $2 to capture the second group and so on.
By using $1${newId}$2 $1 will be replaced with fist captured group - /list and $2 will be replaced with second captured group - (\/?.+)?$. Between these a new ID which is passed in a function param will be inserted.
You should add more checks to make sure there's a proper match, I also tested the regular expression only for these URLs:
https://test.com/list/4
https://test.com/list/4/
https://test.com/list/120
https://test.com/list/120/
https://test.com/list/120/items
https://test.com/list/120/items/240
https://test.com/list/120/items/240/
and it works for these but your real use case might be different.

Related

How can I use regular expressions in react js so that I can you use that in firestore collection name

So I am writing in functional components, I want an expression so that I can retrive that expression collection from firestore database.
So here's the problem.
I need a Six lettered word in which the last three letters should a specific .. eg, CSE
like
group = "CSE"
regExpre = ***+group
//
db.collection({regExpre})
First, you should use RegExp constructor function if the group is dynamic
The below image is specific to CES at the end. It could be anything
const str = "itiCSE",
group = "CSE";
let regex = new RegExp(`^[a-zA-Z]{3}${group}$`);
console.log(regex.test(str));
you are in the right direction,
the regular expression is:
/^[a-zA-Z]{3}(CES)$/g

Regex Negative lookbehind in React app breaking app on iOS devices

After a recent build my app has stopped displaying on iOS devices (just shows a blank screen).
After a log of digging, I've been able to narrow down the cause and it's this regex expression:
(?<!#)
Here's a context how I used it:
/\b(?<!#)gmail\b|\b(?<!#)google\b/i
which means I want to capture the words "gmail" and "google", but only if they are not preceded by an "#" symbol.
My question is, what is the correct regex expression that will do the same job, and work on all browsers/devices?
Thank you
You could capture the words "gmail" and "google", but only if they are not preceded by an "#" symbol by matching them using a non capture group #(?:gmail|google)
Use an alternation | and a capture group (gmail|google) for google or gmail.
#(?:gmail|google)\b|\b(gmail|google)\b
See a regex demo
For example, if you are doing a replacement you could check for the existence of group 1.
const regex = /#(?:gmail|google)\b|\b(gmail|google)\b/g;
const str = `gmail
google
#gmail
#google
test#google.com
#agmail`;
let res = Array.from(str.matchAll(regex), m => m[1] ? `[REPLACED]${m[1]}[REPLACED]` : m[0]);
console.log(res)
You could just directly match a non # character:
/[^#](google|gmail)\b/i
If you need to also match the domain (which can only be google or gmail), then you may access the first capture group.
It seems that a combination of your two answers worked for me:
/[^#](?:gmail|google)\b|\b(gmail|google)\b/i
Thanks!

DNN Rewriting and cutting off Querystring even though I have a Regex setting

Our DNN website is rewriting our product SKU which is part of a Querystring when navigating from a Product Filter Page to a Detailed Product View page.
Unfortunately, some of our products have a forward slash in the SKU for example, BD0002/DSDS
The URL we are navigating to is https://dnndev.me/Product-View/sku/BD0002/DSDS, but DNN would cut off and rewrite the last part of the URL and would result in the following URL: https://dnndev.me/Product-View/sku/BD0002
I did try to add the following Regex code in the SEO settings section of DNN to ignore the re-writing of the page, but it does the same.
sku/(.*)/(.*)
I have also noticed that currently our website writes the sku without the = sign for the querystring. Currently it would be /sku/ and not ?sku= I discovered I can change this when I add |/sku| in the Keep in Querystring Regular Expression.
I have set the URL format to be Advanced in the web.config file. I don't want to change this to HumanFriendly as it breaks our module.
Our product filter page which contains the links to the Product View uses a mustache template with HttpUtility.UrlEncode for QueryStringSKU:
<a href='<%=DetailedPageRedirectLink%>/sku/{{QueryStringSKU}}'>More Info</a>
We then have a Detailed Product View module that listens for the QueryString. I did in the past try to use Encoding and Decoding, but DNN was doing its own thing and ignoring the Encoding and Decoding part so I wrote this crazy part of code that strips out part of the URL that is not part of the SKU.
string rawurlfromrequest = Request.RawUrl;
string checkifquerystringexist = Request.QueryString["sku"];
if(checkifquerystringexist != null)
{
var cleanSKU = rawurlfromrequest.Split(new[] { "sku/" }, StringSplitOptions.None)[1];
decodeprodCode = cleanSKU.Split(new[] { "&" }, StringSplitOptions.None)[0];
decodeprodCode = decodeprodCode.Split(new[] { "/search" }, StringSplitOptions.None)[0];
decodeprodCode = decodeprodCode.Split(new[] { "?fbclid=" }, StringSplitOptions.None)[0];
decodeSKU = HttpUtility.UrlDecode(decodeprodCode);
}
if (!string.IsNullOrWhiteSpace(decodeSKU) && IsEditable == false)
{
LoadProductDetails(decodeSKU);
}
So I would like to know, how can I only allow DNN to rewrite the first part of the URL and not the SKU part of the querystring when it contains a forward slash?
I found these links:
https://www.dnnsoftware.com/answers/disable-friendly-url-for-one-page
https://www.dnnsoftware.com/forums/threadid/542568/scope/posts/how-can-one-turn-off-friendly-urls-url-rewriting-etc-in-dnn-8
I had to escape the query string with uri.EscapedDataString() which will convert the / to %2F as mentioned by VDWWD.
I also discovered that some products contain a space in the SKU which made me decide to use EscapedDataString which will convert a space to %20.
I found this Table with the different Encoding methods on this post useful:
URL Encoding using C#
For some reason Request.Querystring['sku'] fetches the unencoded query string even though it is encoded in the URL. This is why I am using Request.RawUrl and stripping the query string from this.

Gatling: Save random attribute in another attribute

Is it possible to save an attribute at runtime and then save it as another attribute? For instance, I have an ID that is used in the URL, I've captured it from one page, however there are a list of 5 on the page. I can use findAll to select them all, and then ${AttributeName.random()} to select one at random.
However how do I then go and save that as an attribute and then use it elsewhere? As it needs to be the same each time and if I run random again obviously it'll change string each time.
I could do an ${AttributeName(storedRandomNumber)} but the code could start to be a little messy and was wondering if there was something a little cleaner to use?
You could make another exec() right after this request to assign the random value you want with the session.set() method, this value then is saved for the entire thread to be reused.
EX :
val scenario = scenario("scenarioName")
.exec(
http("<-- Name Of Request -->")
.get("<LINK _TO_FIRST_REQ>")
.check(jsonPath("$.items[*].id").findAll.optional.saveAs("ListOfAttributeNames"))
)
.exec( session => session.set("randomAttributeNameSelected", session("ListOfAttributeNames").as[Seq[String]]
.apply(scala.util.Random
.nextInt((session("ListOfAttributeNames").as[Seq[String]].size - 0) + 1)))
)
.exec(
http("We use the ID here")
.get(session => "http://domain.something.com/api/" + session("randomAttributeNameSelected").as[String])
)
Thus anytime in the same thread if you access session("randomAttributeNameSelected").as[String] it will give you random ID.

Catch all url route that allows query parameters

Using ui-router, is there a way to capture a path that contains forward slashes and query parameters?
Let's say there's the catch-all rule in the state configuration:
var exState = {
url: '/example/*path',
...
};
$stateProvider.state(exState);
and then point my browser to
/example/test1?var1=a&var2=b/test2?var3=c&var4=d/
I now see that the forward slashes get encoded:
test1?var1=a&var2=b%2Ftest2%3Fvar3&var4=d%2F
and $stateParams.path is test1 - not what I wanted. Is it possible to get the actual 'raw' path for further processing while avoiding the automatic query parameter capturing which ui-router is doing here?
You can accomplish this but you'll need to use Regex with your URL state, this is from the UI-Router Guide (https://github.com/angular-ui/ui-router/wiki/URL-Routing):
Regex Parameters
A bonus to using curly brackets is the ability to set a Regular Expression rule for the parameter:
// will only match a contactId of one to eight number characters
url: "/contacts/{contactId:[0-9]{1,8}}"
Examples:
'/user/{id:[^/]*}' - Same as '/user/{id}' from the previous example.
'/user/{id:[0-9a-fA-F]{1,8}}' - Similar to the previous example, but only matches if the id parameter consists of 1 to 8 hex digits.
'/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the path into the parameter 'path'.
'/files/*path' - Ditto. Special syntax for catch all.`
This one should catch your url and the parameter string: '/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the path into the parameter 'path'.
EDIT: After capturing the the rest of the URL in the path parameter you'll need to URL decode in order to regain the / & ? and anything else encoded. You can use decodeURIComponent()

Resources