我正在使用github erikras/react-redux-universal-hot-example存储库。
我试图使路线充满活力,以恰当地反映现实世界的情景。
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>
);
服务器的 isomorphic-routes.config.server.js 还调用getRoutes(store)以与客户端进行路由匹配:
match({history, routes: getRoutes(store), location: req.originalUrl},
(error, redirectLocation, renderProps) => {
.....
});
共享 dynamic-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'数组确实接收到路由集合,return语句不会重新处理 确定组件的长度为零,并忽略回调值。
我知道这不是一个React组件,它提供了使用新返回值重新加载的好处,但是,是否有人有任何见解我如何使用回调值返回此JavaScript函数?
谢谢。
答案 0 :(得分:1)
简短的回答是我不仅需要做出决定 dynamic-routes.shared.js 异步,以及任何其他功能 来自服务器&amp;客户端即可。
我用过 关于 dynamic-routes.shared.js 的承诺,以及 async / await 服务器/客户端调用到dynamic-routes.shared.js。
我没有把数据扔进JSON,你可以自己解决这个问题。
<强> 1。动态routes.shared.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。同构-routes.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();
});
};
我希望这有助于任何想要使其同构路线动态化的人。
让美国再次伟大!
答案 1 :(得分:0)
标准解决方案是将getRoutes
设置为遵循React组件生命周期的真实React组件,在这种情况下,当回调返回时可以使用this.setState({ dynRoutes })
来触发重新呈现。在其当前设置中,getRoutes
将永远无法强制调用者/父级重新呈现。
您需要将store.dispatch(loadNav())
调用与组件呈现分开,并构造代码,以便promise处理程序在setState
层次结构中的组件内部触发重新呈现,或再次调用根ReactDOM.render
。