Razzleを使用してReact RouterとReact Loadableを使用して、Next.js のようなデータ フェッチ ( getInitialProps ) を使用するにはどうすればよいですか。react-loadable を使用せずにデータを取得しましたが、コードを分割しないとアプリ バンドルが大きすぎて、クライアントのページを読み込むのに時間がかかりすぎます。
このコードは機能しますが、約 1 年前に行ったことを理解できません (前の例とは少し異なります)。
const promises = routes
.map((route) => {
const match = matchPath(req.url, route)
if (match && route.component) {
let promise
if (typeof route.component.preload === "function") {
promise = route.component.preload()
} else {
promise = Promise.resolve(route.component)
}
return promise
.then((res) => {
return res && res.__esModule ? res.default : res
})
.then((component) => {
let promises = []
// STATIC INTI ACTION
promises.push(store.dispatch(getToken()))
if (component.initialAction) {
let results = component.initialAction({ match })
results = Array.isArray(results)
? results
: [results]
results.forEach((result) => {
promises.push(store.dispatch(result))
})
}
return promises
})
}
return null
})
.filter((el) => el !== null)
// page not found
if (promises.length === 0) {
renderTree(req, res, store)
} else {
Promise.all(promises.map((data) => data.then((moreData) => moreData)))
.then((data) => {
Promise.all(data[0]).then(() => renderTree(req, res, store))
})
サーバー.js
const promises = []
routes.some((route) => {
const match = matchPath(req.url, route);
if (match) {
// route.component is React Loadable Component so getInitialData is undefined
if (route.component.getInitialData) {
promises.push(route.component.getInitialData({ match, req, res }))
}
return true;
}
return false;
});
Promise.all(promises)
.then(renderReact)
.catch(handleError)
// and at the end i will call
Loadable.preloadAll()
.then(sendResponseToUser)
ルート:
[
{
path: "/",
exact: true,
component: Loadable({
loader: () => import("@views/Home"),
loading: Loading,
}),
},
{
path: "/shop",
exact: true,
component: Loadable({
loader: () => import("@views/Shop"),
loading: Loading,
}),
},
]
私のコンポーネントはこのようなものです:
class Home extends React.Component {
// This works similarly to Next.js's `getInitialProps`
static getInitialData({ match, req, res }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
text: `
This text is server rendered if and only if it's the initial render.
Go to another route.
`,
currentRoute: match.pathname,
});
}, 500);
});
}
render() {
return <p>this is just a test</p>
}
}
React Loadable Component には、コンポーネントをロードできる preload() メソッドがあるので、試してみ
route.component.preload()
ましたが、機能しません。
loadable-components を試してみましたが、それにも同じ問題がありますが、react-loadable を loadable-components に置き換えることができます (私の優先ライブラリは loadable-components であり、StrictMode で問題ありません)。
実際、after.jsはこの問題を解決しました (Razzle を使用します)。コード分割ロジックを抽出してアプリで使用するか、データフェッチと反応ロード可能の実際の例があれば、それは素晴らしいことです。