Реагируйте на создание динамического URL с помощью NodeJS - PullRequest
0 голосов
/ 27 октября 2018

Я работаю над React и Node

Теперь я хочу создать динамический URL для отображения профиля пользователя

В Node с EJS мы могли бы просто сделать что-то вроде этого

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

Я взаимодействую либо с помощью вызовов API с помощью axios, либо с помощью перенаправления, чтобы реагировать на адрес веб-страницы.

Теперь я хочу показать профиль пользователя в React, когда кто-то достигнет

 route.get("/:id", function(req, res) {

Вопрос: Так может кто-нибудь сказать, пожалуйста, как я смогу создать приложение динамического реагирования URL?

Ps: я использую реагирующий маршрут для навигации в своем приложении реакции

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 голосов
/ 27 октября 2018

На стороне сервера мы просто отправляем данные и обрабатываем их на стороне клиента, хотя вы также можете обрабатывать их на стороне сервера.

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 проп, чтобы мы могли получить доступ к параметру 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 */);
  }
}
0 голосов
/ 28 октября 2018

Есть 2 подхода (которые мне известны) для решения вашей проблемы, и у обоих есть свои плюсы и минусы.

Подход 1 - Использовать маршруты реакции-маршрутизатора для маршрутизации на стороне клиента,и экспресс / koa маршруты для маршрутизации на стороне сервера.

Это в основном то, что вы показали в своем OP - используйте route.get(...) на стороне сервера и BrowserRouter на стороне клиента.Этот подход имеет потенциал для создания дубликатов обработки маршрутов (и в отдельных местах), что является самой большой проблемой IMO.Дублирование, однако, не является большой проблемой, поскольку оно может быть сведено к минимуму с помощью обычных модулей.Если вы предпочитаете использовать единственное определение маршрута и более унифицированного решения, читайте дальше, подход № 2.

Подход 2 - Используйте маршруты маршрутизации реакции для маршрутизации на стороне сервера и клиента.

Здесь вы должны использовать StaticRouter для маршрутизации на стороне сервера и BrowserRouter для маршрутизации на стороне клиента.Все это очень хорошо изложено в response-router-dom / docs / guides / server-render .Было бы плохо и довольно бессмысленно выполнять копирование и вставку кода из вышеупомянутого документа, но вот некоторые ключевые выводы:

  • ваши маршруты теперь находятся в одном общем месте, скажем ./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")
    );
    

А если вам нужно получить данные или выполнить какую-либо другую гидратацию на сервере, вы можете использовать методы загрузки данных, описанныездесь: Загрузка данных .

Опять же, этот код не является вашим готовым кодом.Необходимо помнить следующие ключевые моменты:

  • создать общее определение маршрута
  • на сервере, отобразить маршруты с помощью StaticRouter
  • на клиенте,рендеринг одних и тех же маршрутов с использованием BrowserRouter
  • вы можете использовать обещания или async / await для гидратации приложения на сервере, используя файл определения маршрута, если это необходимо (axios, isomorphic-fetch и т. д. - хорошие библиотеки, которые работают на обоих серверахи клиент одинаково хорошо).

Если я неправильно понял ваш вопрос, и если все, что вы хотите знать, это как создать 2 маршрута, которые могут различать / и /:id;тогда, в дополнение к тому, что я упомянул выше, я бы сказал, что теперь нужно просто упорядочить маршруты и сопоставить их с точностью.Таким образом, вы можете сначала определить свой маршрут :/id, а затем свой маршрут /, чтобы предотвратить столкновение, или изменить свои маршруты так, чтобы они были семантически правильными, например users/:id.

реагирующий маршрутизатор (и большинство всех маршрутизаторов) будет соответствовать / практически для всего.exact опора делает его консервативным, но это скорее пластырь.Вам было бы лучше, если бы вы оставили / на своей домашней странице и определили маршруты как entity/:id в целом.

0 голосов
/ 27 октября 2018

Нет простого или короткого способа объяснить это, но вот пример, чтобы вы начали ... Допустим, у вас был сайт портфолио, и там у вас были отдельные пункты портфолио ...

Вот как вы делаете динамическую маршрутизацию с реакции-маршрутизатором:

Ваш маршрутизатор:

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

Тогда вот ваш ProfolioPage:

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

И, наконец, ваш PortfolioItemPage (Вы можете получить доступ к этому идентификатору через {props.match.params.id} - см. ниже):

const PortfolioItem = (props) => (
  <div>
    <h1>A Thing I've Done</h1>
    <p>This page is for the item with the id of {props.match.params.id}</p>
  </div>
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...