使用NodeJS反应创建动态URL

时间:2018-10-27 19:59:36

标签: node.js reactjs react-router

我正在研究React和Node

现在,我想创建一个动态URL以显示用户个人资料

在使用EJS的Node中,我们可以简单地完成这样的事情

route.get("/:id", function(req, res) {
  playground.find({}, function (error, plyground) { //MongoDb find syntex
    if (error) {
     console.log(error);
    } else {
 playground.findById(req.params.id).populate("comments").exec(function(error, playground)  {
    if (error) {
      console.log("error -> Show route or more information about playground")
    }
    else {
      res.render("playground/show", {playground:playground, plyground:plyground})
    }
  });
}
})
})

在这里,由于EJS和Node都在同一地址上工作,因此,每当用户到达/:id时,它将从数据库中找到用户信息并进行渲染。

如果有反应,我的节点应用程序正在localhost:8080上运行,而反应应用程序在localhost:3000

我通过使用axios进行API调用或重定向以响应网页地址来进行交互。

现在,我想在有人到达

时在React中显示用户个人资料
 route.get("/:id", function(req, res) {

问题:有人可以告诉我如何创建动态URL react应用程序吗?

Ps:我正在使用react-route在我的React应用中导航

import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom'
//Remaining imports 

const route = () => {
    return(
    <BrowserRouter>
      <div>
      <Switch>
        <Route path ="/" exact render ={(props) => <Home {...props}/>} />
        <Route path ="/signup" exact render ={(props) => <Signup {...props}/>} />
        <Route path ="/Home" exact render={(props) => <MainHomeScreen {...props}/>} />
    </Switch>
      </div>
    </BrowserRouter>
    )
}

export default route;

3 个答案:

答案 0 :(得分:2)

没有一个简单或简短的解释方法,但这是一个使您前进的示例...假设您有一个投资组合站点,并且在其中有单独的投资组合项...

以下是使用react-router进行动态路由的方法:

您的路由器:

const get = endPoint => {
  return new Promise((resolve, reject) => {
    MyToken().then(token => {
      ...
      fetch(endPoint, lookupOptions)
      .then(response => response.json())
      .then(resolvedResponse => {
        resolve(resolvedResponse);
      }).catch(error => {
        reject(error);
      });
    });
  });
};

然后这是您的ProfolioPage:

const AppRouter = () => (
  <BrowserRouter>
    <div>
      <Switch>
        <Route path="/portfolio" component={PortfolioPage} exact={true} />
        <Route path="/portfolio/:id" component={PortfolioItemPage} />
      </Switch>
    </div>
  </BrowserRouter>
);

最后是您的PortfolioItemPage(您可以通过const PortfolioPage = () => ( <div> <h1>My Work</h1> <p>Checkout the stuff I've done:</p> <Link to="/portfolio/1">Item One</Link> <Link to="/portfolio/2">Item Two</Link> </div> ); 访问该ID-见下文):

{props.match.params.id}

答案 1 :(得分:2)

在服务器端,我们只是发送数据,然后在客户端进行处理,尽管您也可以在服务器端进行渲染。

route.get("/:id", (req, res) => {
    const data = getDataFromDB(req.params.id);
    res.send(data);
});

现在在反应方面,让我们从路由开始吧

<Switch>
  <Route path ="/:id" render ={(props) => <DisplayData {...props}/>} />
</Switch>

现在react-router-dom注入了一个match道具,我们可以像express一样访问id参数。

因此,在DisplayData组件中,我们添加了componentDidMount生命周期挂钩,该挂钩将基于id参数获取数据并设置状态。

class DisplayData extends Component {
  componentDidMount = () => {
    const id = this.props.match.params.id;
    axios(id)
      .then(data => this.setState({ data }))
      .catch(err => /* do something */);
  }
}

答案 2 :(得分:2)

有2种方法(据我所知)可以解决您的问题,并且各有利弊。

方法1 -使用react-router路由进行客户端路由,并使用express / koa路由进行服务器端路由。

这基本上就是您在OP中显示的内容-在服务器端使用route.get(...)在客户端使用BrowserRouter。这种方法有可能创建重复的路线处理(在单独的地方),这是最大的海事组织。但是,重复并不是一个大问题,因为可以使用通用模块在一定程度上将其最小化。如果您希望使用单个路由定义以及更多统一解决方案,请继续阅读方法2。

方法2 -在服务器和客户端路由中都使用react-router路由。

在这里,您将使用StaticRouter进行服务器端路由,使用BrowserRouter进行客户端路由。这些都很好地布置在react-router-dom/docs/guides/server-rendering上。复制上面文档中的代码粘贴是一种无益且毫无意义的练习,但这是一些关键要点:

  • 您的路线现在位于一个共同的地方,例如./shared/routes.js
  • 您的js看起来像

    // app.js
    import { routes } from "./shared/routes.js";
    
    const App = () => (
    <Switch>
        {routes.map(route => (
            <Route {...route} />
        ))}
    </Switch>
    );
    
    // server.js
    import { createServer } from "http";
    import React from "react";
    import ReactDOMServer from "react-dom/server";
    import { StaticRouter } from "react-router";
    import App from "./App";
    
    createServer((req, res) => {
        const context = {};
    
        const html = ReactDOMServer.renderToString(
            <StaticRouter location={req.url} context={context}>
                <App />
            </StaticRouter>
        );
    
        if (context.url) {
            res.writeHead(301, { Location: context.url });
            res.end();
        } else {
            res.write(`
            <!doctype html>
            <div id="app">${html}</div>
            `);
            res.end();
        }
    }).listen(3000);
    
    // or if using express/koa
    app.get('/*', (req, res) => {
        const context = {};
        const app = ReactDOMServer.renderToString(
            <StaticRouter location={req.url} context={context}>
                <App />
            </StaticRouter>
        );
        ...
    })
    
    // client.js
    import ReactDOM from "react-dom";
    import { BrowserRouter } from "react-router-dom";
    import App from "./App";
    
    ReactDOM.render(
        <BrowserRouter>
            <App />
        </BrowserRouter>,
        document.getElementById("app")
    );
    

如果您需要在服务器上获取数据或进行其他水化处理,则可以使用此处介绍的数据加载技术:Data Loading

同样,此代码不是您的生产就绪代码。要记住的关键点是您需要:

  • 创建通用路线定义
  • 在服务器上,使用StaticRouter
  • 渲染路线
  • 在客户端上,使用BrowserRouter渲染相同的路线
  • 如果需要,您可以使用promise或async / await在服务器上使用路由定义文件对应用程序进行水化处理(axios,isomorphic-fetch等是可以在服务器和客户端上同时工作的良好库)。

如果我误解了您的问题,并且您只想知道如何创建两条可以区分//:id的路线,然后,我要说的是,除了上面提到的内容外,现在您需要做的只是简单地确定路线并精确匹配。因此,您可以先定义:/id路由,然后再定义/路由以防止冲突,或者将路由修改为语义上正确的东西,例如users/:id

反应路由器(以及大多数路由器)几乎都与/相匹配。 exact道具使其较为保守,但这只是一个创可贴。最好将/留在首页并将路线定义为entity/:id,这样会更好。