简体   繁体   English

React 服务器端只渲染特定的路由

[英]React server side rendering only specific routes

I currently have a website built using EJS and using express on the backend on port 3300 .我目前有一个使用 EJS 构建的网站,并在端口3300的后端使用 express 。 The structure of the routes look like this:路由的结构如下所示:

localhost:3300
-/movies
   -/rating
   -/review
-/tvshows
   -/rating
   -/review

I am currently returning EJS files in the routes like this:我目前在这样的路线中返回 EJS 文件:

router.get("/:title/rating", function(req, res) {
    Movie.find({ movieName: req.params.title })
    .exec(function(err, foundMovie) {
        if (err) {
            console.log(err);
        } else {
            console.log(foundMovie)
            res.render("movie/rating", { movie: foundMovie});        
        }
    });
});

But now, I want to add a new route in the structure that uses React such that the following will be built using React:但是现在,我想在使用 React 的结构中添加一条新路由,以便使用 React 构建以下内容:

localhost:3300
-/documentary
    -/rating
    -/review

From my understanding, if I want to use React, I would have to re-write all my previous routes (that returns EJS) as React components since you can't merge the two servers (React and Express as they both run on different ports: 3000 and 3300 respectively).据我了解,如果我想使用 React,我将不得不将我以前的所有路由(返回 EJS)重写为 React 组件,因为您无法合并这两个服务器(React 和 Express,因为它们都在不同的端口上运行:分别为30003300 )。 But since I have so much written already I tried to render the new routes on the serverside by following this tutorial resulting in:但是由于我已经写了很多东西,所以我尝试按照本教程在服务器端呈现新路由,结果是:

router.get("/documentary", (req,res) => {
    Documentary.find({}).exec(function(err,foundDoc){
        if (err){
            console.log(err);
        } else {
            fs.readFile(path.resolve("./views/react/client/build/index.html"), "utf-8", (err, data) => {
                if (err) {
                  return res.status(500).send("Error");
                }
                return res.send(
                  data.replace(
                    '<div id="root"></div>',
                    `<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
                  )
                );
              });
        }
    })
});

And App.js looking like: App.js 看起来像:

function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/rating">
          <h1>Rating page for Documentaries</h1>
        </Route>  
        <Route exact path="/review">
          <h1>Review page for Documentaries</h1>
        </Route>
      </Switch>
    </BrowserRouter>
      );
    }

I get an error: Error: Invariant failed: Browser history needs a DOM at invariant我得到一个错误: Error: Invariant failed: Browser history needs a DOM at invariant

How do I fix the error?我该如何修复错误? Or is there a better way to combine both EJS routes and create new React routes?或者是否有更好的方法来组合 EJS 路由并创建新的 React 路由? Thanks in advance提前致谢

Issue问题

You need to use a different Router in the server as well.您还需要在服务器中使用不同的Router Since BrowserRouter in the client React app cannot be processed in the server.由于客户端 React 应用程序中的BrowserRouter无法在服务器中处理。

Static Router is what you're looking for. Static 路由器就是您要找的。

Solution解决方案

Server-side rendering in React is very tricky. React中的服务器端渲染非常棘手。 I recommend you to use Nextjs which makes it easy.我建议你使用Nextjs ,这很容易。

For side-projects , refer to this blog对于side-projects请参阅此博客

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM