简体   繁体   English

如何使用React可加载和获取组件数据(如Next.js)进行服务器端渲染?

[英]How to do Server Side Rendering in React With React Loadable and Fetching Data for Components (Like Next.js)?

How Can i have Next.js Like Data Fetching ( getInitialProps ) with React Router and React Loadable using Razzle . 我如何使用反射路由器和使用Razzle React可加载的数据获取( getInitialProps )Next.js。 I had data fetching without react-loadable but without code splitting app bundle is too big and it's taking too long to load the page for clients. 没有反应加载的数据提取但没有代码拆分应用程序包太大而且为客户端加载页面花费的时间太长。

this code works, but I just don't understand what I did about a year ago (it's a little bit different from the previous example) 这段代码有效,但我只是不明白一年前我做了什么(它与前面的例子略有不同)

    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))
            })

Server.js Server.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)

routes: 路线:

[
    {
        path: "/",
        exact: true,
        component: Loadable({
            loader: () => import("@views/Home"),
            loading: Loading,
        }),
    },
    {
        path: "/shop",
        exact: true,
        component: Loadable({
            loader: () => import("@views/Shop"),
            loading: Loading,
        }),
    },
]

My Components are Like This: 我的组件是这样的:

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 have preload() method that can load Component so i tried: route.component.preload() but it's not working. React可加载组件有preload()方法,可以加载组件,所以我尝试: route.component.preload()但它不工作。

I tried loadable-components and it has the same problem with that too but I can replace react-loadable with loadable-components(my preferred library is loadable-components cause it's ok with StrictMode). 我尝试了可加载的组件,它也有同样的问题,但我可以用可加载的组件替换反应加载(我的首选库是可加载组件,因为它可以使用StrictMode)。

actually, after.js solved this problem (it uses Razzle) if I could extract code splitting logic and use it in my app or have some working example of data-fetching and react-loadable together it would be awesome. 实际上, after.js解决了这个问题(它使用Razzle),如果我可以提取代码分裂逻辑并在我的应用程序中使用它,或者有一些数据获取反应可加载的工作示例,那将是非常棒的。

This is how i did this. 这就是我这样做的方式。

Its working with both. 它与两者合作。 loadable Components and normal components. 可加载组件和普通组件。

Inside matchRoutes(). 里面的matchRoutes()。 check for component.preload. 检查component.preload。

If its true, then allow it to load component.preload(). 如果为true,则允许它加载component.preload()。

This will return a promise And after promise resolves, we will get our component. 这将返回一个承诺。在承诺结算后,我们将获得我们的组件。 Then check for loadData/getInitialProps/fetchData, whatever static method name we are using. 然后检查loadData / getInitialProps / fetchData,无论我们使用什么静态方法名称。

return res.default.loadData ? res.default.loadData(store) : null;

you can call server side fetch request .. i am calling it loadData() 你可以调用服务器端获取请求..我正在调用它loadData()

Always remember to return the promise, because its a chain of promise. 永远记住要回报承诺,因为它是一连串的承诺。

Aslo inside your redux actions, always remember to return the dispatch(). 在你的redux动作中,总是记得返回dispatch()。

 app.get('*', (req, res) => { // store instance for every incoming request const store = createStore(req); // loadData from api... before rendering const promises = matchRoutes(Routes, req.path) .map((comp) => { console.log(comp, comp.route.component.loadData) if (comp.route.component.preload){ console.log("LoadableComponent") comp.route.component.preload().then(res => { return res.default.loadData ? res.default.loadData(store) : null; }) } return comp.route.component.loadData ? comp.route.component.loadData(store) : null; }) .map(promise => { if (promise) { return new Promise((resolve, reject) => { promise.then(resolve).catch(resolve); }); } }); Promise.all(promises).then(() => { console.log(store.getState()) const context = {}; const content = renderer(req, store, context); if (context.url) { return res.redirect(301, context.url); } if (context.notFound) { res.status(404); } Loadable.preloadAll().then(() => { res.send(content); }); }); }); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Next.js:如何将仅外部客户端的 React 组件动态导入到开发的服务器端渲染应用程序中? - Next.js: How to dynamically import external client-side only React components into Server-Side-Rendering apps developed? 使用 Next.js 对服务器端渲染进行 React Query - React Query with server side rendering using Next.js 如何在广泛使用 React hooks 的同时利用 Next.js 服务器端渲染? - How do I take advantage of Next.js server-side rendering while using React hooks extensively? 如何让 Next.js 做 SSR(服务器端渲染)? - How to make Next.js do SSR (Server Side Rendering)? 使用webpack 3进行react-loadable和服务器端渲染 - react-loadable and server side rendering with webpack 3 react-html5video是否与服务器端渲染兼容? (使用next.js) - Is react-html5video is compatible with server side rendering ?? (Using next.js) 在 Next.js 和/或其他形式的 React 服务器端渲染中延迟加载图像 - Lazy Loading Images in Next.js and/or in other forms of React server-side rendering 我们如何处理 Next.js 服务器端渲染 SSR 的构建时数据获取与实时数据? - How do we deal with the build time data fetch vs real time data for Next.js Server Side Rendering SSR? 服务器端在 React 中使用 Next.js 加载全局组件 - Server side load a global component with Next.js in React 通过 Next.js 在服务器端渲染中反应 State - React State in Server Side Render Via Next.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM