我在尝试使用 reactDomServer 和静态路由器进行服务器端渲染时遇到错误。
我得到以下输出:
Error: Invariant failed: You should not use <Switch> outside a <Router>
at invariant (webpack:///./node_modules/tiny-invariant/dist/tiny-invariant.esm.js?:14:9)
at Object.eval [as children] (webpack:///./node_modules/react-router/esm/react-router.js?:658:88)
at ReactDOMServerRenderer.render (/home/jesusap21/jps_webapp/node_modules/react-dom/cjs/react-dom-server.node.development.js:3635:55)
at ReactDOMServerRenderer.read (/home/jesusap21/jps_webapp/node_modules/react-dom/cjs/react-dom-server.node.development.js:3373:29)
at Object.renderToString (/home/jesusap21/jps_webapp/node_modules/react-dom/cjs/react-dom-server.node.development.js:3988:27)
at Server.<anonymous> (/home/jesusap21/jps_webapp/src/ssr/http.js:23:37)
at Server.emit (events.js:198:13)
at parserOnIncoming (_http_server.js:691:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:111:17)
我的服务器:
http.createServer((req, res) => {
// This context object contains the results of the render
const context = {};
const html = ReactDOMServer.renderToString(
<ReactRouter.StaticRouter location={req.url} context={context}>
<App />
</ReactRouter.StaticRouter>
);
// context.url will contain the URL to redirect to if a <Redirect> was used
if (context.url) {
res.writeHead(302, {
Location: context.url
});
} else {
res.write(html);
}
res.end();
}).listen(port);
我在客户端使用 BrowserRouter,并且使用相同的组件“App”可以正常工作。但在服务器端我遇到了这个问题。
** 编辑 **
这是我的应用程序组件代码:
import React from 'react';
import configureStore from './store/configureStore';
import { Provider } from 'react-redux';
import Container from './Container'
const store = configureStore();
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Container />
</Provider>
)
}
}
然后是我的容器
function Container(props: LinkStateProp) {
const theme = createMuiTheme({
palette: {
primary: {
light: 'rgba(153, 28, 31, 0.4)',
main: '#C8283B',
contrastText: '#FFFFFF',
},
secondary: {
light: '#F2F2F2',
main: 'rgba(0, 0, 0, 0.08)',
dark: 'rgba(0, 0, 0, 0.2)',
contrastText: '#000000',
},
contrastThreshold: 3,
tonalOffset: 0.2,
},
typography: {
fontFamily: "Roboto",
}
});
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
},
layout: {
marginTop: '10vh',
minHeight: '90vh',
display: 'flex',
}
}),
);
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Switch>
<MuiThemeProvider theme={theme}>
<Container className={classes.root} maxWidth={false} disableGutters={true}>
<Nav open={open} handleDrawerOpen={handleDrawerOpen} handleDrawerClose={handleDrawerClose}/>
<LeftDrawer open={open} handleDrawerClose={handleDrawerClose}/>
<div className={classes.layout}>
<Route exact path="/" component={Home}/>
<Route exact path="/iniciarsesion">
{props.isAuthUser ? <Redirect to="/" /> : <SignIn />}
</Route>
<Route exact path="/crearcuenta">
{props.isAuthUser ? <Redirect to="/" /> : <SignUp />}
</Route>
</div>
</Container>
</MuiThemeProvider>
</Switch>
);
}
interface LinkStateProp {
isAuthUser: boolean,
}
const mapStateToProps = (state: ApplicationState) => ({
isAuthUser: state.customer.isAuthUser,
});
export default connect(mapStateToProps)(Container);