reactjs - useMatch för flera mönster att testa på i react-router-dom
Jag har följande array:
const tabsList = [
{
pathPattern: 'users/'
label: 'Manage users'
},
{
pathPattern: 'users/:id',
label: 'Edit user profile'
}
]
Jag behöver en metod från react-router-dom för att tala om vilken av ovanstående arrayposter som matchar den aktuella sökvägen.
Baserat på det kommer jag att kunna färga det aktiva listobjektet i mina komponentstilar.
Jag hittade metoden useMatch() som verkar göra nästan vad jag vill, men den accepterar inte en array, den accepterar endast ett strängmönster att använda för jämförelse.
// example: current path is /users/82374023854321
const isAllUsersMatch = useMatch('/users') // null
const isUserIdMatch = useMatch('/users/:id') // { ...PathMatch<string> }
det fungerar, men det är inte bra, jag måste skapa en separat variabel på det sättet för varje objekt i arrayen.
Finns det något liknande följande i react-router-dom?
const tabsList = [
{
pathPattern: 'users/'
label: 'Manage users'
},
{
pathPattern: 'users/:id',
label: 'Edit user profile'
}
]
const activeListItem = tabsList.some((listItem)=> doesItMatch(listItem.pathPattern))
Jag skulle ha gjort detta med hooken, men i React kan du inte använda en hook inuti en callback, så följande skulle inte fungera:
// const activeListItem = tabsList.some((listItem)=> doesItMatch(listItem.pathPattern))
const activeListItem = tabsList.some((listItem)=> useMatch(listItem.pathPattern)) // ERROR
Svar #1
Du är på rätt spår när du itererar över tabsList-arrayen. Om allt du behöver är att matcha den aktuella vägen med en i ett konfigurationsobjekt/array, kan du istället för att använda useMatch-hooken, som inte fungerar i en nästlad callback-funktion, använda matchPath-hjälpfunktionen som useMatch-hooken använder direkt.
import { matchPath, useLocation } from "react-router-dom";
const tabsList = [
{
pathPattern: "users/",
label: "Manage users"
},
{
pathPattern: "users/:id",
label: "Edit user profile"
}
];
...
const { pathname } = useLocation();
const activeListItem = tabsList.find(({ pathPattern }) =>
matchPath(pathPattern, pathname)
);
Och ovanstående abstrakterat till en anpassad hook:
const useTabsListMatches = (tabsList = []) => {
const { pathname } = useLocation();
return tabsList.find(({ pathPattern }) =>
matchPath(pathPattern, pathname)
);
}
const activeListItem = useTabsListMatches(tabsList);
Svar #2
Du kan förmodligen använda react-router's matchRoutes() om du ändrar formen på ditt objekt:
const location = useLocation()
const matches = matchRoutes([{
path: 'users/',
label: 'Manage users',
}, {
path: 'users/:id',
label: 'Edit user profile',
}], location)
