Add custom Redirect component
react-router v4 was made before React introduced a more performant function renderToNodeStream to replace renderToString. All guides for react-router are made using renderToString method, but I would love to use the renderToNodeStream instead. Since we cannot issue a 302 redirect after the page has already been rendered (because status codes are written first), we can display a <a> link with a text message. Once the React client-side library hydrates the DOM Tree, the redirect should happen client side, so no user action should be required. This idea was taken from: https://github.com/ReactTraining/react-router/issues/6191
This commit is contained in:
parent
3fae7adc4a
commit
cf8aefd099
48
packages/client/src/components/Redirect.test.tsx
Normal file
48
packages/client/src/components/Redirect.test.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react'
|
||||
import {renderToString} from 'react-dom/server'
|
||||
import T from 'react-dom/test-utils'
|
||||
import {Redirect} from './Redirect'
|
||||
import {LocationDescriptorObject} from 'history'
|
||||
import {
|
||||
MemoryRouter,
|
||||
// Redirect as RouterRedirect,
|
||||
Route,
|
||||
} from 'react-router-dom'
|
||||
|
||||
function getJSX(to: LocationDescriptorObject | string = '/test1234') {
|
||||
return (
|
||||
<MemoryRouter initialEntries={['/two']}>
|
||||
<Route path='/one' render={() => <span>Ok</span>} />
|
||||
<Route path='/two' render={() => <Redirect to={to} />} />
|
||||
</MemoryRouter>
|
||||
)
|
||||
}
|
||||
|
||||
describe('Redirect - client side', () => {
|
||||
it('renders a redirect component', () => {
|
||||
T.renderIntoDocument(getJSX())
|
||||
})
|
||||
})
|
||||
|
||||
describe('Redirect - server side', () => {
|
||||
const g: any = global
|
||||
const window = g.window
|
||||
beforeEach(() => {
|
||||
delete g.window
|
||||
})
|
||||
afterEach(() => {
|
||||
g.window = window
|
||||
})
|
||||
|
||||
it('renders a href component', () => {
|
||||
const html = renderToString(getJSX())
|
||||
expect(html).toContain('<a href="/test1234">here</a>')
|
||||
})
|
||||
|
||||
it('handles LocationDescriptorObject', () => {
|
||||
const html = renderToString(getJSX({
|
||||
pathname: '/test1234',
|
||||
}))
|
||||
expect(html).toContain('<a href="/test1234">here</a>')
|
||||
})
|
||||
})
|
||||
22
packages/client/src/components/Redirect.tsx
Normal file
22
packages/client/src/components/Redirect.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
import {Redirect as RouterRedirect} from 'react-router-dom'
|
||||
import {RedirectProps} from 'react-router'
|
||||
import {isClientSide} from '../renderer'
|
||||
|
||||
export class Redirect extends React.PureComponent<RedirectProps> {
|
||||
render() {
|
||||
if (isClientSide()) {
|
||||
return <RouterRedirect {...this.props}/>
|
||||
}
|
||||
|
||||
const href = typeof this.props.to === 'string'
|
||||
? this.props.to : this.props.to.pathname
|
||||
|
||||
return (
|
||||
<span>
|
||||
You are being redirected.
|
||||
Click <a href={href}>here</a> to 'continue'
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './Button'
|
||||
// export * from './Component'
|
||||
export * from './Input'
|
||||
export * from './Redirect'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user