使用 React/Redux 的服务器端呈现,获取 url 参数以传递到 loadData
Server Side Rendering with React/Redux, getting url params to pass into loadData
我很确定为什么这不起作用,但我不确定如何解决它。
我有一个组件,它在末尾使用 loadData()
函数,以便将数据传递到商店成为 SSR。
示例组件类似于
class Test extends Component {
render(){
return (
<div>Test</div>
)
}
}
const loadData = store => {
return store.dispatch(actions.getRecord(this.props.match.params.id));
};
export default {
component: Test,
loadData: loadData
}
这里的问题是 this.props.match.params.id
是未定义的,特别是在 props 部分。我知道这是因为我不在组件内部,如何从其中的 URL 访问参数?
万一这有帮助,我也会展示我的 SSR 部分:
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';
import routes from './src/routes';
import createStore from './src/stores';
function handleRender(req, res) {
const store = createStore.configure(null); // create Store in order to get data from redux
const promises = matchRoutes(routes, req.path)
.map(({ route }) => {
// Matches the route and loads data if loadData function is there
return route.loadData ? route.loadData(store) : null;
})
.map(promise => {
if (promise) {
return new Promise((resolve, reject) => {
promise.then(resolve).catch(resolve); // lets all data load even if route fails
});
}
});
Promise.all(promises).then(() => {
const context = {};
if (context.url) {
return res.redirect(301, context.url); // redirect for non auth users
}
if (context.notFound) {
res.status(404); // set status to 404 for unknown route
}
const content = renderToString(
<Provider store={store}>
<StaticRouter location={req.path} context={context}>
<div>{renderRoutes(routes)}</div>
</StaticRouter>
</Provider>
);
const initialState = serialize(store.getState());
const helmet = Helmet.renderStatic();
res.render('index', { content, initialState, helmet });
});
}
module.exports = handleRender;
每个 matchRoutes 项中都有一个 match
属性,您可以将其传递到 loadData
函数中:
matchRoutes(routes, req.path)
.map(({ route, match }) => {
return route.loadData ? route.loadData(store, match) : Promise.resolve(null);
})
然后您的 loadData 函数可以访问它:
const loadData = (store, match) => store.dispatch(reduxAction(match.params.id))
我很确定为什么这不起作用,但我不确定如何解决它。
我有一个组件,它在末尾使用 loadData()
函数,以便将数据传递到商店成为 SSR。
示例组件类似于
class Test extends Component {
render(){
return (
<div>Test</div>
)
}
}
const loadData = store => {
return store.dispatch(actions.getRecord(this.props.match.params.id));
};
export default {
component: Test,
loadData: loadData
}
这里的问题是 this.props.match.params.id
是未定义的,特别是在 props 部分。我知道这是因为我不在组件内部,如何从其中的 URL 访问参数?
万一这有帮助,我也会展示我的 SSR 部分:
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';
import routes from './src/routes';
import createStore from './src/stores';
function handleRender(req, res) {
const store = createStore.configure(null); // create Store in order to get data from redux
const promises = matchRoutes(routes, req.path)
.map(({ route }) => {
// Matches the route and loads data if loadData function is there
return route.loadData ? route.loadData(store) : null;
})
.map(promise => {
if (promise) {
return new Promise((resolve, reject) => {
promise.then(resolve).catch(resolve); // lets all data load even if route fails
});
}
});
Promise.all(promises).then(() => {
const context = {};
if (context.url) {
return res.redirect(301, context.url); // redirect for non auth users
}
if (context.notFound) {
res.status(404); // set status to 404 for unknown route
}
const content = renderToString(
<Provider store={store}>
<StaticRouter location={req.path} context={context}>
<div>{renderRoutes(routes)}</div>
</StaticRouter>
</Provider>
);
const initialState = serialize(store.getState());
const helmet = Helmet.renderStatic();
res.render('index', { content, initialState, helmet });
});
}
module.exports = handleRender;
每个 matchRoutes 项中都有一个 match
属性,您可以将其传递到 loadData
函数中:
matchRoutes(routes, req.path)
.map(({ route, match }) => {
return route.loadData ? route.loadData(store, match) : Promise.resolve(null);
})
然后您的 loadData 函数可以访问它:
const loadData = (store, match) => store.dispatch(reduxAction(match.params.id))