react-router-dom v6 StaticRouter 上下文不工作
react-router-dom v6 StaticRouter context is not working
我正在尝试制作 SSR React 网络应用程序。
除 staticContext 外一切正常。
我的服务器代码是
// IMPORTS
const renderer = (req, store, context) => {
const content = renderToString(
<Provider store={store}>
<ThemeProvider theme={responsiveFontSizes(theme)}>
<CssBaseline />
<StaticRouter location={req.path} context={context}>
<Navigation />
<main>
{renderRoutes(MainRouter)}
</main>
<Footer />
</StaticRouter>
</ThemeProvider>
</Provider>
);
const helmet = Helmet.renderStatic();
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="icon" href="${process.env.REACT_APP_URL}/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="${process.env.REACT_APP_THEME_COLOR}" />
${helmet.title.toString()}
${helmet.meta.toString()}
<link rel="stylesheet" href="main.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
</head>
<body>
<noscript>Pre dokonalé fungovanie tejto webovej aplikácie povoľte JavaScript.</noscript>
<div id="root">${content}</div>
<script>
window.INITIAL_STATE = ${serialize(store.getState())}
</script>
<script src="bundle.js"></script>
</body>
</html>
`;
};
app.get('*', (req, res) => {
const store = createStore();
var promises = matchRoutes(MainRouter, req.path).map(route => {
return route?.loadData ? route.loadData(store) : [];
});
promises.push(loadData(store, req.cookies));
Promise.all(promises).then(() => {
const context = {};
const content = renderer(req, store, context);
if(context.url) {
return res.redirect(302, context.url);
}
if(context.notFound) {
console.log('404');
res.status(404);
};
res.send(content);
});
});
而我的404组件客户端代码是
const NotFound = ({ staticContext = {} }) => {
staticContext.notFound = true;
const head = () => (
<Helmet>
<title>{process.env.REACT_APP_NAME} – Stránka sa nenašla</title>
</Helmet>
);
return (
<React.Fragment>
{head()}
<section>
{/* Some content */}
</section>
</React.Fragment>
)
};
export default {
Component: NotFound
};
此行应将 notFound = true 参数传递到请求中:
staticContext.notFound = true;
因此这部分代码应将请求状态设置为 404 并将控制台日志设置为“404”字符串:
if(context.notFound) {
console.log('404');
res.status(404);
};
但是没用。
我的代码是否有可能被弃用?
我正在使用所有依赖项的当前最新稳定版本。
我的 package.json 依赖项
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.5",
"axios": "0.24.0",
"babel-cli": "6.26.0",
"babel-core": "6.26.3",
"babel-loader": "8.2.3",
"compression": "1.7.4",
"concurrently": "6.5.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"date-fns": "^2.27.0",
"express": "4.17.2",
"lodash": "4.17.21",
"nodemon": "2.0.15",
"npm-run-all": "4.1.5",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-helmet": "6.1.0",
"react-redux": "^7.2.6",
"react-router-dom": "6.2.1",
"react-spinners": "^0.11.0",
"redux": "^4.1.2",
"serialize-javascript": "6.0.0",
"universal-cookie": "^4.0.4",
"webpack": "5.65.0",
"webpack-dev-server": "4.7.1",
"webpack-merge": "5.8.0",
"webpack-node-externals": "3.0.0"
Is it possible that my code is deprecated?
恐怕是。
这是 v6.0.0-alpha.4 的主要变化之一:
Removed the <StaticRouter context>
API. We don't support navigation on the initial render in v6, so this API is unnecessary.
我最终将状态代码和重定向 URL 存储在 Redux 存储中,并在渲染后在渲染服务器上检查它们。
对于状态代码,我在 NotFound
页面组件的 loadData
函数中调度了 setStatus(404)
操作。
这是我的重定向解决方案 URL:
// router.js
import {useRoutes} from 'react-router-dom';
import getRoutes from '@client/router/routes';
import {useAuthSelector} from '@client/store/slices/auth';
export default ({ssr = false}) => {
const {currentUser} = useAuthSelector();
return useRoutes(getRoutes(currentUser, ssr));
};
// routes.js
import requireAuth from './requireAuth';
import App from '@client/App';
import Home from '@client/pages/Home';
import Users from '@client/pages/Users';
import Admins from '@client/pages/Admins';
import NotFound from '@client/pages/NotFound';
export default (currentUser = false, ssr = false) => {
const protectedRoute = requireAuth(currentUser, ssr);
return [
{
...App,
children: [
{
path: '/',
...Home,
},
{
path: '/users',
...Users,
},
{
path: '/admins',
...protectedRoute(Admins),
},
{path: '*', ...NotFound},
],
},
];
};
// requireAuth.js
import React from 'react';
import {Navigate} from 'react-router-dom';
import {setRedirectUrl} from '@client/store/slices/http';
export default (currentUser, ssr = false) => (component) => {
switch (currentUser) {
case false:
if (ssr) {
// If the user is not logged in and the SSR is happening
const loadData = component.loadData;
component.loadData = (store) => {
// Call the original loadData if component has one
loadData && loadData(store);
store.dispatch(setRedirectUrl('/'));
};
} else {
// If the user is not logged in
component.element = <Navigate to='/' replace />;
}
break;
case null:
component.element = <div>Loading...</div>;
break;
default:
return component;
}
return component;
};
当我在渲染服务器上使用我的路由器时,我只是将 ssr
属性设置为 true。
想到的另一种方法是使用 React 上下文而不是 Redux 存储。
我在使用 SSR 的 StaticRouter 时遇到一般性导入错误,并从 Google 登陆此页面(粘贴错误时)。如果其他人有类似的问题,似乎在 react-router-dom
v6 中 StaticRouter
现在应该从 react-router-dom/server
.
导入
我正在尝试制作 SSR React 网络应用程序。 除 staticContext 外一切正常。
我的服务器代码是
// IMPORTS
const renderer = (req, store, context) => {
const content = renderToString(
<Provider store={store}>
<ThemeProvider theme={responsiveFontSizes(theme)}>
<CssBaseline />
<StaticRouter location={req.path} context={context}>
<Navigation />
<main>
{renderRoutes(MainRouter)}
</main>
<Footer />
</StaticRouter>
</ThemeProvider>
</Provider>
);
const helmet = Helmet.renderStatic();
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="icon" href="${process.env.REACT_APP_URL}/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="${process.env.REACT_APP_THEME_COLOR}" />
${helmet.title.toString()}
${helmet.meta.toString()}
<link rel="stylesheet" href="main.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
</head>
<body>
<noscript>Pre dokonalé fungovanie tejto webovej aplikácie povoľte JavaScript.</noscript>
<div id="root">${content}</div>
<script>
window.INITIAL_STATE = ${serialize(store.getState())}
</script>
<script src="bundle.js"></script>
</body>
</html>
`;
};
app.get('*', (req, res) => {
const store = createStore();
var promises = matchRoutes(MainRouter, req.path).map(route => {
return route?.loadData ? route.loadData(store) : [];
});
promises.push(loadData(store, req.cookies));
Promise.all(promises).then(() => {
const context = {};
const content = renderer(req, store, context);
if(context.url) {
return res.redirect(302, context.url);
}
if(context.notFound) {
console.log('404');
res.status(404);
};
res.send(content);
});
});
而我的404组件客户端代码是
const NotFound = ({ staticContext = {} }) => {
staticContext.notFound = true;
const head = () => (
<Helmet>
<title>{process.env.REACT_APP_NAME} – Stránka sa nenašla</title>
</Helmet>
);
return (
<React.Fragment>
{head()}
<section>
{/* Some content */}
</section>
</React.Fragment>
)
};
export default {
Component: NotFound
};
此行应将 notFound = true 参数传递到请求中:
staticContext.notFound = true;
因此这部分代码应将请求状态设置为 404 并将控制台日志设置为“404”字符串:
if(context.notFound) {
console.log('404');
res.status(404);
};
但是没用。 我的代码是否有可能被弃用? 我正在使用所有依赖项的当前最新稳定版本。
我的 package.json 依赖项
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.5",
"axios": "0.24.0",
"babel-cli": "6.26.0",
"babel-core": "6.26.3",
"babel-loader": "8.2.3",
"compression": "1.7.4",
"concurrently": "6.5.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"date-fns": "^2.27.0",
"express": "4.17.2",
"lodash": "4.17.21",
"nodemon": "2.0.15",
"npm-run-all": "4.1.5",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-helmet": "6.1.0",
"react-redux": "^7.2.6",
"react-router-dom": "6.2.1",
"react-spinners": "^0.11.0",
"redux": "^4.1.2",
"serialize-javascript": "6.0.0",
"universal-cookie": "^4.0.4",
"webpack": "5.65.0",
"webpack-dev-server": "4.7.1",
"webpack-merge": "5.8.0",
"webpack-node-externals": "3.0.0"
Is it possible that my code is deprecated?
恐怕是。
这是 v6.0.0-alpha.4 的主要变化之一:
Removed the
<StaticRouter context>
API. We don't support navigation on the initial render in v6, so this API is unnecessary.
我最终将状态代码和重定向 URL 存储在 Redux 存储中,并在渲染后在渲染服务器上检查它们。
对于状态代码,我在 NotFound
页面组件的 loadData
函数中调度了 setStatus(404)
操作。
这是我的重定向解决方案 URL:
// router.js
import {useRoutes} from 'react-router-dom';
import getRoutes from '@client/router/routes';
import {useAuthSelector} from '@client/store/slices/auth';
export default ({ssr = false}) => {
const {currentUser} = useAuthSelector();
return useRoutes(getRoutes(currentUser, ssr));
};
// routes.js
import requireAuth from './requireAuth';
import App from '@client/App';
import Home from '@client/pages/Home';
import Users from '@client/pages/Users';
import Admins from '@client/pages/Admins';
import NotFound from '@client/pages/NotFound';
export default (currentUser = false, ssr = false) => {
const protectedRoute = requireAuth(currentUser, ssr);
return [
{
...App,
children: [
{
path: '/',
...Home,
},
{
path: '/users',
...Users,
},
{
path: '/admins',
...protectedRoute(Admins),
},
{path: '*', ...NotFound},
],
},
];
};
// requireAuth.js
import React from 'react';
import {Navigate} from 'react-router-dom';
import {setRedirectUrl} from '@client/store/slices/http';
export default (currentUser, ssr = false) => (component) => {
switch (currentUser) {
case false:
if (ssr) {
// If the user is not logged in and the SSR is happening
const loadData = component.loadData;
component.loadData = (store) => {
// Call the original loadData if component has one
loadData && loadData(store);
store.dispatch(setRedirectUrl('/'));
};
} else {
// If the user is not logged in
component.element = <Navigate to='/' replace />;
}
break;
case null:
component.element = <div>Loading...</div>;
break;
default:
return component;
}
return component;
};
当我在渲染服务器上使用我的路由器时,我只是将 ssr
属性设置为 true。
想到的另一种方法是使用 React 上下文而不是 Redux 存储。
我在使用 SSR 的 StaticRouter 时遇到一般性导入错误,并从 Google 登陆此页面(粘贴错误时)。如果其他人有类似的问题,似乎在 react-router-dom
v6 中 StaticRouter
现在应该从 react-router-dom/server
.