React Router/Redux-动态同构路由
React-Router/Redux - Dynamic Isomorphic Routes
我在github工作erikras/areact-redux通用热门示例存储库。
我正在努力使路线具有动态性,以恰当地反映真实世界的场景。
-
client/entry.js页面调用一个传递存储参数的共享模块函数"getRoutes"。
const component = ( <Router render={(props) => <ReduxAsyncConnect {...props} helpers={{client}} filter={item => !item.deferred} /> } history={history}> // where the routes are populated {getRoutes(store)} // <-- function call </Router>
);
-
服务器的同构路由config.server.js也调用getRoutes(store)与客户端进行路由匹配:
match({history, routes: getRoutes(store), location: req.originalUrl}, (error, redirectLocation, renderProps) => { ..... });
-
shareddynamic routes.shared.js页面是一个reg JavaScript函数"getRoutes":
export default (store) => { ...... let dynRoutes= []; store.dispatch(loadNav()).then(result => { dynRoutes = result; }) return ( <Route path="/" component={App}> { /* Home (main) route */ } <IndexRoute component={Home}/> { /* Get dynamic routes from database */ } { dynRoutes.length > 0 ? <DynamicRoutes dynRoutes={dynRoutes} /> : ''} { /* Catch all route */ } <Route path="*" component={NotFound} status={404} /> </Route> ) };
在第二次"复飞"时,dynRoutes的数组确实接收到routes集合,return语句不会重新处理,并且组件被确定为具有零长度,并且回调值被忽略。
我知道这不是一个React组件,它提供了用新的返回值重新加载的好处,但是,有人知道我如何让这个JavaScript函数用回调值返回吗?
谢谢。
简而言之,我不仅需要动态路由.共享.js异步,
还有任何其他函数调用,来自服务器和;客户端
我用过在动态路由上承诺。shared.js,在服务器/客户端调用到动态路由.shared.js。
我没有费心将数据放入JSON中,您几乎可以自己解决这个问题。
1.动态路由.共享.js
function routesWithStore(store) {
return new Promise(function(resolve, reject) {
// you can use something like this to actually have these
// routes in a database
// let dynRoutes= [];
// store.dispatch(loadNav()).then(result => {
// dynRoutes = result;
// })
// resolve(dynRoutes.map(route => {
// ..... your code here .....
// }))
resolve(
{
path: '',
component: App,
childRoutes: [
{path: '/', component: Home},
{path: 'home', component: Home},
{path: 'about', component: About},
{path: '*', component: NotFound}
]
}
)
});
}
function getRoutes(store) {
return(
routesWithStore(store)
)
}
exports.getRoutes = getRoutes;
2.client/entry.js
// async call to dynamic-routes.shared.js ////////
async function main() {
try {
const result = await getRoutes(store);
processRoutes(result);
} catch(err) {
console.log(err.message)
}
}
function processRoutes(result) {
const component = (
<Router render={(props) =>
<ReduxAsyncConnect {...props} helpers={{client}}
filter={item => !item.deferred} />
} history={history}>
{result} <------------- client value from dynamic-routes.shared.js
</Router>
);
ReactDOM.render(
<Provider store={store} key="provider">
{component}
</Provider>,
document.querySelector('#root');
);
_
if (process.env.NODE_ENV !== 'production') {
window.React = React; // enable debugger
if (!dest || !dest.firstChild
|| !dest.firstChild.attributes
|| !dest.firstChild.attributes['data-react-checksum']) {
console.error
('Server-side React render was discarded. ' +
'Make sure that your initial render does not contain any client-side code.');
}
}
if (__DEVTOOLS__ && !window.devToolsExtension) {
const DevTools = require('shared/redux/dev-tools/dev-tools.redux.shared');
ReactDOM.render(
<Provider store={store} key="provider">
<div>
{component}
<DevTools />
</div>
</Provider>,
document.querySelector('#root');
);
}
}
main();
3.同构路由.config.server
module.exports = (app) => {
app.use((req, res) => {
if (__DEVELOPMENT__) {
// Do not cache webpack stats: the script file would change since
// hot module replacement is enabled in the development env
webpackIsomorphicTools.refresh();
}
const client = new ApiClient(req);
const memoryHistory = createHistory(req.originalUrl);
const store = createStore(memoryHistory, client);
const history = syncHistoryWithStore(memoryHistory, store);
function hydrateOnClient() {
res.send('<!doctype html>'n' +
ReactDOM.renderToString(
<Html assets={webpackIsomorphicTools.assets()}
store={store}/>));
}
if (__DISABLE_SSR__) {
hydrateOnClient();
return;
}
_
// Async call to dynamic-routes.shared.js ////////
async function main() {
try {
const routesResult = await getRoutes(store);
// pass routesResult below
match({history, routes: routesResult, location: req.originalUrl},
(error, redirectLocation, renderProps) => {
if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search);
} else if (error) {
console.error('ROUTER ERROR:', pretty.render(error));
res.status(500);
hydrateOnClient();
_
} else if (renderProps) {
loadOnServer({...renderProps, store, helpers: {client}}).then(() => {
const component = (
<Provider store={store} key="provider">
<ReduxAsyncConnect {...renderProps} />
</Provider>
);
res.status(200);
global.navigator = {userAgent: req.headers['user-agent']};
res.send('<!doctype html>'n' +
ReactDOM.renderToString(
<Html assets={webpackIsomorphicTools.assets()}
component={component} store={store}/>));
});
} else {
res.status(404).send('Iso Routes Not Found ' + routeResult);
}
});
} catch(error) {
console.error(error);
}
}
main();
});
};
我希望这能帮助任何想要使同构路由动态化的人
让美国再次伟大!
标准解决方案是将getRoutes
设置为遵循React组件生命周期的真实React组件,在这种情况下,当回调返回时可以使用this.setState({ dynRoutes })
来触发重新渲染。在其当前设置中,getRoutes
将永远无法强制调用方/父级重新渲染。
您需要将store.dispatch(loadNav())
调用与组件呈现分离,并对代码进行结构化,以便promise处理程序使用setState
或再次调用根ReactDOM.render
触发组件内部的重新呈现。
- 同构reactjs-cdn资产
- renderReact/Rect Router+Node/Express.js的服务器端/同构渲染中未定义renderP
- 同构获取不适用于外部请求
- Javascript 同构三元运算符无法正确解析
- 同构反应.js无通量
- 在同构应用程序中使用redux
- 单元测试通用/同构节点包文件
- 如何在同构应用程序中通过节点提取传递请求cookie
- 同构JS应用程序中的环境变量:Webpackfind&代替
- 同构ReactJS-如何为服务器端和客户端共享代码
- 同构反应.js&iso http
- `同构的fetch`response.json()方法总是抛出意外的输入结束错误
- 在同构的React web应用程序中,选择服务器渲染的最佳方式是什么
- 测试ReactJs中使用的同构获取
- 角度 2 是同构的吗?将来会不会
- 如何将同构的 commonJS 代码与 webpack 捆绑在一起
- 同构反应-路由器-冗余同步历史中间件
- 节点.js同构反应示例错误
- 服务器端路由是否与服务器端呈现/同构javascript相同
- React Router/Redux-动态同构路由