-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
extends: '@bamdadsabbagh/eslint-config', | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: 2 | ||
updates: | ||
|
||
- package-ecosystem: "github-actions" | ||
directory: "/" | ||
schedule: | ||
interval: "daily" | ||
|
||
- package-ecosystem: "npm" | ||
directory: "/" | ||
schedule: | ||
interval: "daily" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: semantic-release-yarn--onPush | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
semantic-release-yarn--onPush: | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- uses: actions/checkout@master | ||
|
||
- uses: actions/setup-node@master | ||
with: | ||
node-version: '14' | ||
|
||
- run: yarn | ||
|
||
- run: | | ||
npm install -g \ | ||
semantic-release \ | ||
@semantic-release/github \ | ||
@semantic-release/git \ | ||
@semantic-release/exec \ | ||
@semantic-release/changelog \ | ||
@semantic-release/npm \ | ||
semantic-release-chrome \ | ||
semantic-release-firefox-add-on \ | ||
aggregate-error | ||
- run: semantic-release | ||
env: | ||
GH_TOKEN: ${{ secrets.PAT }} | ||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
FIREFOX_API_KEY: ${{ secrets.FIREFOX_API_KEY }} | ||
FIREFOX_SECRET_KEY: ${{ secrets.FIREFOX_SECRET_KEY }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
yarn-error.log | ||
.idea/sonarlint/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
Replace URL parameters in Next.js without re-rendering. | ||
|
||
## 🚀 Getting Started | ||
|
||
```bash | ||
npm install next-replace-url | ||
yarn add next-replace-url | ||
``` | ||
|
||
```javascript | ||
import {useNextReplaceUrl, nextReplaceUrl} from 'next-replace-url'; | ||
|
||
// in your functional component | ||
useNextReplaceUrl('parameter', value); | ||
|
||
// from anywhere | ||
nextReplaceUrl('parameter', value); | ||
``` | ||
|
||
## 📖️ Description | ||
|
||
The module replaces the `window.history.state` object therefore bypassing Next.js routing context, avoiding re-renders. | ||
|
||
Some suggest shallow routing which unfortunately does not prevent re-renders. | ||
|
||
### Under the hood example | ||
|
||
```javascript | ||
// User navigates to https://example.com/audio/1 | ||
|
||
// Current state | ||
window.history.state = { | ||
"url": "/audio/[volume]?volume=1", // Next.js URL | ||
"as": "/audio/1" // What user sees | ||
} | ||
|
||
// Running the following command will replace the URL parameter "volume" with "2" | ||
nextReplaceUrl('volume', '2') | ||
|
||
// Resulting state | ||
window.history.state = { | ||
"url": "/audio/[volume]?volume=2", | ||
"as": "/audio/2" | ||
} | ||
``` | ||
|
||
## 📖️ Related discussions | ||
|
||
- https://github.com/vercel/next.js/discussions/18072 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
{ | ||
"name": "next-replace-url", | ||
"version": "0.0.0", | ||
"description": "Replace URL parameters in Next.js without re-rendering", | ||
"author": { | ||
"name": "Bamdad Sabbagh", | ||
"email": "[email protected]", | ||
"url": "https://bamdad.fr" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/bamdadsabbagh/next-replace-url.git" | ||
}, | ||
"license": "MIT", | ||
"keywords": [ | ||
"next", | ||
"next.js", | ||
"replace", | ||
"url", | ||
"route", | ||
"parameter", | ||
"parameters", | ||
"param", | ||
"params", | ||
"render", | ||
"re-render", | ||
"rendering", | ||
"re-rendering", | ||
"query", | ||
"string", | ||
"querystring", | ||
"query-string", | ||
"history" | ||
], | ||
"type": "module", | ||
"main": "src/main.js", | ||
"types": "src/main.d.ts", | ||
"files": [ | ||
"src" | ||
], | ||
"scripts": { | ||
"package:reinstall": "rimraf node_modules && yarn", | ||
"package:sort": "npx sort-package-json" | ||
}, | ||
"devDependencies": { | ||
"@bamdadsabbagh/eslint-config": "^2.0.21", | ||
"react": "^18.0.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module.exports = { | ||
plugins: [ | ||
'@semantic-release/commit-analyzer', | ||
'@semantic-release/release-notes-generator', | ||
['@semantic-release/changelog', { | ||
changelogFile: 'CHANGELOG.md', | ||
}], | ||
['@semantic-release/npm', { | ||
npmPublish: true, | ||
}], | ||
'@semantic-release/github', | ||
['@semantic-release/git', { | ||
assets: [ | ||
'CHANGELOG.md', | ||
'package.json', | ||
], | ||
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}', | ||
}], | ||
], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
declare module 'next-replace-url' { | ||
/** | ||
* Replace URL parameters in Next.js without re-rendering | ||
* | ||
* @param {string} parameter - Route parameter | ||
* @param {string} value - New parameter value | ||
*/ | ||
export function nextReplaceUrl(parameter: string, value: string): void; | ||
|
||
/** | ||
* React Hook for replacing URL parameter in Next.js without re-rendering | ||
* | ||
* @param {string} parameter - Route parameter | ||
* @param {string} value - New parameter value | ||
*/ | ||
export function useNextReplaceUrl(parameter: string, value: string): void; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export {nextReplaceUrl} from './next-replace-url.js'; | ||
export {useNextReplaceUrl} from './use-next-replace-url.js'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* Replace URL parameters in Next.js without re-rendering | ||
* | ||
* @param {string} parameter - Route parameter | ||
* @param {string} value - New parameter value | ||
*/ | ||
export function nextReplaceUrl(parameter, value) { | ||
if (typeof parameter !== 'string') { | ||
throw new Error('parameter is not a string'); | ||
} | ||
|
||
if (typeof value !== 'string') { | ||
throw new Error('value is not a string'); | ||
} | ||
|
||
// Current state | ||
const {as, url} = window.history.state; | ||
const args = as.split('/'); | ||
|
||
// Find the parameter index | ||
const parameterId = new RegExp(`^(.*)(\\[${parameter}\\])(.*)$`) | ||
.exec(url) | ||
.slice(1)[0] | ||
.split('/') | ||
.length - 1; | ||
|
||
// Replace value | ||
args[parameterId] = value; | ||
|
||
// Build the new state | ||
const newAs = args.join('/'); | ||
const newUrl = url.replace( | ||
new RegExp(`${parameter}=.*?(?=&|$)`), | ||
`${parameter}=${value}`, | ||
); | ||
|
||
// Apply the new state | ||
window.history.replaceState( | ||
{...window.history.state, as: newAs, url: newUrl}, | ||
'', | ||
newAs, | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {useEffect} from 'react'; | ||
import {nextReplaceUrl} from './next-replace-url'; | ||
|
||
/** | ||
* React Hook for replacing URL parameter in Next.js without re-rendering | ||
* | ||
* @param {string} parameter - Route parameter | ||
* @param {string} value - New parameter value | ||
*/ | ||
export function useNextReplaceUrl(parameter, value) { | ||
useEffect(() => { | ||
nextReplaceUrl(parameter, value); | ||
}, [parameter, value]); | ||
} |