Skip to content

Commit

Permalink
fix: Handle external redirects
Browse files Browse the repository at this point in the history
  • Loading branch information
franky47 committed Apr 13, 2020
1 parent 2d69580 commit 54187d6
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 3 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,22 @@ export default () => (
)
```

If you want to [redirect to an external link](https://github.com/zeit/next.js/blob/master/errors/invalid-href-passed.md)
(not an internal route), you will have to set the `external` prop:

```tsx
import { Redirect } from '@47ng/chakra-next'

export default () => (
<>
<Redirect to="https://example.com" external />

{/* You can also have the history replaced with external URLs: */}
<Redirect to="https://example.com" external replace />
</>
)
```

### Containers

```tsx
Expand Down
29 changes: 29 additions & 0 deletions src/components/redirect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,33 @@ describe('Redirect', () => {
expect(fakeRouter.push.mock.calls[0][0]).toEqual('/foo/[slug]')
expect(fakeRouter.push.mock.calls[0][1]).toEqual('/foo/bar')
})

test('external URL - push', () => {
fakeRouter.push = jest.fn()
fakeRouter.replace = jest.fn()
delete window.location
window.location = Object.assign(new URL('http://localhost'), {
assign: jest.fn(),
replace: jest.fn(),
}) as any
render(<Redirect to="https://example.com" external />)
expect(fakeRouter.push).not.toHaveBeenCalled()
expect(fakeRouter.replace).not.toHaveBeenCalled()
expect(window.location.assign).toHaveBeenCalledWith('https://example.com')
expect(window.location.replace).not.toHaveBeenCalled()
})
test('external URL - replace', () => {
fakeRouter.push = jest.fn()
fakeRouter.replace = jest.fn()
delete window.location
window.location = Object.assign(new URL('http://localhost'), {
assign: jest.fn(),
replace: jest.fn(),
}) as any
render(<Redirect to="https://example.com" external replace />)
expect(fakeRouter.push).not.toHaveBeenCalled()
expect(fakeRouter.replace).not.toHaveBeenCalled()
expect(window.location.replace).toHaveBeenCalledWith('https://example.com')
expect(window.location.assign).not.toHaveBeenCalled()
})
})
18 changes: 15 additions & 3 deletions src/components/redirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,32 @@ export interface RedirectProps {
to: string
as?: string
replace?: boolean
external?: boolean
}

export const Redirect: React.FC<RedirectProps> = ({
to,
as = to,
replace = false,
external = false,
}) => {
const router = useRouter()

React.useEffect(() => {
if (replace) {
router.replace(to, as)
if (external) {
// Support redirection to external URLs:
// https://err.sh/zeit/next.js/invalid-href-passed
if (replace) {
window.location.replace(as)
} else {
window.location.assign(as)
}
} else {
router.push(to, as)
if (replace) {
router.replace(to, as)
} else {
router.push(to, as)
}
}
}, [])

Expand Down

0 comments on commit 54187d6

Please sign in to comment.