it-roy-ru.com

URL-адреса React-маршрутизатора не работают при обновлении или записи вручную

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

Например, я нахожусь в localhost/joblist и все хорошо, потому что я приехал сюда, нажимая на ссылку. Но если я обновлю веб-страницу, я получу:

Cannot GET /joblist

По умолчанию это не сработало. Первоначально у меня были URL как localhost/#/ и localhost/#/joblist, и они работали отлично. Но мне не нравится этот вид URL, поэтому, пытаясь стереть этот #, я написал:

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

Эта проблема не возникает с localhost/, эта всегда возвращает то, что я хочу.

EDIT: Это приложение одностраничное, поэтому /joblist не нужно ничего спрашивать ни на одном сервере.

EDIT2: Весь мой роутер.

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});
455
DavidDev

Глядя на комментарии к принятому ответу и общий характер этого вопроса ("не работает"), я подумал, что это может быть хорошим местом для некоторых общих объяснений по вопросам, связанным с этим. Таким образом, этот ответ предназначен в качестве справочной информации/разработки по конкретному варианту использования ОП. Пожалуйста, потерпите меня.

Сторона сервера против стороны клиента

Первая важная вещь, которую нужно понять, это то, что теперь есть 2 места, где URL интерпретируется, тогда как раньше было "1" в "старые времена". В прошлом, когда жизнь была проста, какой-то пользователь отправлял запрос на http://example.com/about на сервер, который проверял часть пути URL-адреса, определял, что пользователь запрашивает страницу about, а затем отправлял эту страницу обратно.

С маршрутизацией на стороне клиента, которую предоставляет React-Router, все не так просто. Во-первых, у клиента еще нет загруженного кода JS. Так что самый первый запрос всегда будет на сервер. Затем будет возвращена страница, содержащая необходимые теги сценариев для загрузки React и React маршрутизатора и т.д. Только после загрузки этих сценариев начинается фаза 2. На этапе 2, когда пользователь нажимает, например, на навигационную ссылку "О нас", URL-адрес изменяется только локально на http://example.com/about (становится возможным благодаря History API) ), но запрос к серверу не производится . Вместо этого React Маршрутизатор делает свое дело на стороне клиента, определяет, какой React вид должен отображаться, и отображает его. Предполагая, что вашей странице about не нужно делать никаких REST вызовов, это уже сделано. Вы перешли из дома в О нас без каких-либо запросов к серверу.

Поэтому, в основном, когда вы щелкаете ссылку, запускается какой-то Javascript, который манипулирует URL-адресом в адресной строке , не вызывая обновление страницы , что, в свою очередь, заставляет маршрутизатор React выполнять переход страницы на стороне клиента .

Но теперь подумайте, что произойдет, если скопировать и вставить URL-адрес в адресную строку и отправить его другу по электронной почте. Ваш друг еще не загрузил ваш сайт. Другими словами, она все еще находится в фазе 1 . React Маршрутизатор еще не запущен на ее компьютере. Поэтому ее браузер отправит запрос к серверу на http://example.com/about.

И вот тут начинается твоя проблема. До сих пор вы могли бы просто разместить статический HTML в корне вашего сервера. Но это приведет к ошибкам 404 для всех других URL при запросе с сервера . Те же URL-адреса работают нормально на стороне клиента , потому что там React Маршрутизатор выполняет маршрутизацию за вас, но они терпят неудачу на сервере сторона , если вы не заставите свой сервер понять их.

Объединение серверной и клиентской маршрутизации

Если вы хотите, чтобы URL-адрес http://example.com/about работал как на стороне сервера, так и на стороне клиента, вам необходимо настроить для него маршруты как на стороне сервера, так и на стороне клиента. Имеет смысл правильно?

И вот тут начинается ваш выбор. Решения варьируются от полного обхода проблемы через универсальный маршрут, который возвращает HTML bootstrap, до полного изоморфного подхода, когда и сервер, и клиент выполняют один и тот же код JS.

,.

Обход проблемы в целом: Hash History

Если Hash History вместо Browser History , ваш URL для страницы about будет выглядеть примерно так: http://example.com/#/about Часть после символа хеша (#) не отправляется на сервер , Таким образом, сервер видит только http://example.com/ и отправляет страницу индекса, как и ожидалось. React-Router подберет часть #/about и покажет правильную страницу.

Downsides :

  • "уродливые" URL
  • При таком подходе рендеринг на стороне сервера невозможен. Что касается поисковой оптимизации (SEO), ваш сайт состоит из одной страницы, на которой почти нет контента.

,.

Вместилище разнообразных предметов

При таком подходе вы используете историю браузеров, но просто настраиваете всеобъемлющую информацию на сервере, который отправляет /* в index.html, что фактически дает вам ту же ситуацию, что и с Hash History. Тем не менее, у вас есть чистые URL-адреса, и вы могли бы улучшить эту схему позже, не делая недействительными все избранное вашего пользователя.

Downsides :

  • Более сложная настройка
  • Все еще нет хорошего SEO

,.

Гибридный

В гибридном подходе вы расширяете общий сценарий, добавляя конкретные сценарии для определенных маршрутов. Вы можете сделать несколько простых PHP сценариев, чтобы вернуть наиболее важные страницы вашего сайта с включенным содержимым, чтобы робот Googlebot мог хотя бы увидеть, что находится на вашей странице.

Downsides :

  • Еще сложнее настроить
  • Только хороший SEO для тех маршрутов, которые вы предоставляете специальную обработку
  • Дублирование кода для рендеринга контента на сервере и клиенте

,.

Изоморфный

Что если мы используем Node JS в качестве нашего сервера, чтобы мы могли запускать один и тот же код JS на обоих концах? Теперь у нас есть все наши маршруты, определенные в одной конфигурации реакции-маршрутизатора, и нам не нужно дублировать наш код рендеринга. Это, так сказать, "Святой Грааль". Сервер отправляет ту же самую разметку, которую мы получили бы в случае перехода страницы на клиенте. Это решение является оптимальным с точки зрения SEO.

Downsides :

  • Сервер должен (быть в состоянии) запускать JS. Я экспериментировал с Java i.c.w. Нашорн, но это не работает для меня. На практике это в основном означает, что вы должны использовать Node сервер на основе JS.
  • Многие сложные экологические проблемы (использование window на стороне сервера и т.д.)
  • Крутая кривая обучения

,.

Какой я должен использовать?

Выберите тот, который вы можете сойти с рук. Лично я думаю, что все достаточно просто настроить, так что это мой минимум. Эта настройка позволяет вам улучшать вещи с течением времени. Если вы уже используете Node JS в качестве серверной платформы, я бы определенно занялся созданием изоморфного приложения. Да, сначала это сложно, но как только вы освоитесь, это на самом деле очень элегантное решение проблемы.

В общем, для меня это было бы решающим фактором. Если мой сервер работает на Node JS, я бы стал изоморфным; В противном случае я бы выбрал решение Catch-all и просто расширил его (Гибридное решение), когда время идет, а требования SEO требуют этого.

Если вы хотите больше узнать об изоморфном (также называемом "универсальным") рендеринге с помощью React, есть несколько хороших учебников по этому вопросу:

Кроме того, чтобы начать, я рекомендую взглянуть на некоторые стартовые наборы. Выберите тот, который соответствует вашему выбору для технологического стека (помните, React - это просто V в MVC, вам нужно больше материала для создания полноценного приложения). Начните с просмотра того, что опубликовано самим Facebook:

Или выберите один из множества сообществ. Теперь есть хороший сайт, который пытается проиндексировать их все:

Я начал с этого:

В настоящее время я использую самодельную версию универсального рендеринга, которая была вдохновлена ​​двумя вышеперечисленными стартовыми наборами, но сейчас они устарели.

Удачи в вашем квесте!

803
Stijn de Witt

Все ответы здесь очень полезны, для меня работало то, что я настроил мой сервер Webpack для ожидания маршрутов.

  devServer: {
    historyApiFallback: true,
    contentBase: './',
    hot: true
  },

HistoryApiFallback - это то, что исправило эту проблему для меня. Теперь маршрутизация работает правильно, и я могу обновить страницу или ввести URL-адрес напрямую. Не нужно беспокоиться об обходах на вашем сервере узлов. Этот ответ, очевидно, работает только при использовании веб-пакета.

Правка: см. Мой ответ здесь для более подробной причины, почему это необходимо: https://stackoverflow.com/a/37622953/5217568

93
jmancherje

Для React Router V4 пользователей:

Если вы попытаетесь решить эту проблему с помощью техники Hash History, упомянутой в других ответах, обратите внимание, что

<Router history={hashHistory} >

не работает в V4, используйте вместо этого HashRouter:

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

Ссылка: https://reacttraining.com/react-router/web/api/HashRouter

44
user2875289

Вы можете изменить свой htaccess и вставить это:

RewriteBase /
RewriteRule ^index\.html$ - [L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

Я использую react: "^15.3.2", react-router: "^3.0.0", history: "^4.3.0",

41
BrahimS

Маршрутизатор можно вызывать двумя различными способами, в зависимости от того, происходит ли навигация на клиенте или на сервере. Он настроен для работы на стороне клиента. Ключевым параметром является второй в метод выполнения , местоположение.

Когда вы используете компонент React Router Link, он блокирует навигацию в браузере и вызывает transitionTo для выполнения навигации на стороне клиента. Вы используете HistoryLocation, поэтому он использует API истории HTML5, чтобы завершить иллюзию навигации, имитируя новый URL в адресной строке. Если вы используете старые браузеры, это не сработает. Вам нужно будет использовать компонент HashLocation.

Когда вы нажмете "Обновить", вы обойдете весь код маршрутизатора React и ​​React. Сервер получает запрос на /joblist и должен что-то вернуть. На сервере вам нужно передать запрошенный путь методу run, чтобы он отображал правильное представление. Вы можете использовать ту же карту маршрутов, но вам, вероятно, понадобится другой вызов Router.run. Как указывает Чарльз, вы можете использовать переписывание URL для этого. Другой вариант - использовать сервер node.js для обработки всех запросов и передачи значения пути в качестве аргумента location.

В экспрессе, например, это может выглядеть так:

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

Обратите внимание, что путь запроса передается run. Для этого вам понадобится механизм просмотра на стороне сервера, в который вы можете передать обработанный HTML. Существует ряд других соображений, касающихся использования renderToString и запуска React на сервере. Как только страница отображается на сервере, когда ваше приложение загружается в клиент, оно будет отображаться снова, обновляя отображаемый HTML на стороне сервера по мере необходимости.

27
Todd

В ваш index.html head добавьте следующее:

<base href="/">
<!-- This must come before the css and javascripts -->

Затем при работе с сервером webpack dev используйте эту команду.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback является важной частью

19
Efe Ariaroo

У сервера Webpack Dev есть возможность включить это. Откройте package.json и добавьте --history-api-fallback. Это решение работало для меня.

https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls#configuring-your-server

14
srijishks

Я использовал create-реагировать на приложение, чтобы сделать веб-сайт только что и тот же вопрос, представленный здесь. Я использую BrowserRouting из пакета react-router-dom. Я работаю на сервере Nginx, и я решил добавить следующее в /etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

Что соответствует добавлению следующего к .htaccess в случае, если вы запускаете Appache

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Это также, кажется, решение, предложенное самими Facebook и может быть найдено здесь

14
Aidin

Если вы размещаете приложение реагирования через AWS Static S3 Hosting & CloudFront

Эта проблема возникла из-за того, что CloudFront ответил сообщением 403 "Отказано в доступе", поскольку ожидалось, что/некоторый/другой/путь будет существовать в моей папке S3, но этот путь существует только внутри маршрутизации React с реакции-маршрутизатором.

Решением было настроить правило распространения страниц ошибок. Перейдите в настройки CloudFront и выберите свой дистрибутив. Далее перейдите на вкладку "Страницы ошибок". Нажмите "Создать пользовательский ответ об ошибке" и добавьте запись для 403, так как это код ошибки, который мы получаем. Установите для параметра "Путь к странице ответа" значение /index.html, а для кода состояния - значение 200. Конечный результат поражает своей простотой. Страница индекса обслуживается, но URL-адрес сохраняется в браузере, поэтому, как только приложение реакции загружается, оно обнаруживает путь URL-адреса и переходит к нужному маршруту.

Правило страницы ошибок 4

12
th3morg

Это может решить вашу проблему

Я также столкнулся с той же проблемой в приложении ReactJS в режиме производства. Вот 2 решения проблемы.

1. Измените историю маршрутизации на "hashHistory" вместо browserHistory вместо

 <Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
 </Router>

Теперь создайте приложение с помощью команды

Sudo npm run build

Затем поместите папку сборки в папку var/www /. Теперь приложение работает нормально с добавлением тега # в каждый URL. лайк

localhost/#/home localhost/#/aboutus

Решение 2. Без тега # с помощью browserHistory,

Установите вашу историю = {browserHistory} в вашем маршрутизаторе, теперь соберите его, используя команду sudo npm run build.

Вам нужно создать файл "conf" для решения страницы 404 not found, файл conf должен быть таким.

откройте свой терминал введите ниже команды

cd/etc/Apache2/sites-available ls nano sample.conf Добавьте в него приведенный ниже контент.

 <VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${Apache_LOG_DIR}/error.log
    CustomLog ${Apache_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

Теперь вам нужно включить файл sample.conf с помощью следующей команды

cd /etc/Apache2/sites-available
Sudo a2ensite sample.conf

затем он попросит перезагрузить сервер Apache, используя службу Sudo. Перезагрузите или перезапустите Apache2.

затем откройте папку localhost/build и добавьте файл .htaccess с содержанием ниже.

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

Теперь приложение работает нормально.

Примечание: измените 0.0.0.0 ip на ваш локальный IP-адрес.

Если есть сомнения по этому поводу, не стесняйтесь поднять комментарий.

Я надеюсь, что это полезно для других.

12
Venkatesh Somu

Производственный стек: React, React Router v4, BrowswerRouter, Express, Nginx

1) Пользователь BrowserRouter для красивых URL

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2) Добавьте index.html ко всем неизвестным запросам, используя /*

// server.js

app.get('/*', function(req, res) {   
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

3) связать веб-пакет с webpack -p

4) запустить nodemon server.js или node server.js

Правка: Вы можете позволить nginx обрабатывать это в блоке сервера и игнорировать шаг 2:

location / {
    try_files $uri /index.html;
}
9
Isaac Pak

добавьте это в webpack.config.js

devServer: {
      historyApiFallback: true
  }
8
suraj

Попробуйте добавить файл ".htaccess" в общую папку с помощью приведенного ниже кода.

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  
6
Kiran Joshi

Если вы используете приложение Создать React:

Тем не менее, эта проблема отлично подходит для решений для многих основных хостинговых платформ, которые вы можете найти ЗДЕСЬ на странице создания React приложения. Например, я использую React Router v4 и Netlify для моего кода веб-интерфейса. Все, что нужно, это добавить 1 файл в мою общую папку ("_redirects") и одну строку кода в этом файле:

/*  /index.html  200

Теперь мой веб-сайт правильно отображает пути, такие как mysite.com/pricing, при входе в браузер или при обновлении.

5
Colton Hicks

Если вы размещаете свое приложение реагирования в IIS, просто добавьте файл web.config, содержащий:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

Это скажет серверу IIS, что нужно возвращать главную страницу клиенту вместо ошибки 404 и не нужно использовать историю хешей.

3
Chtiwi Malek

Эта тема немного устарела и решаема, но я хотел бы предложить вам простое, ясное и лучшее решение. Это работает, если вы используете веб-сервер.

Каждый веб-сервер имеет возможность перенаправить пользователя на страницу ошибки в случае http 404. Для решения этой проблемы вам необходимо перенаправить пользователя на страницу индекса.

Если вы используете базовый сервер Java (Tomcat или любой сервер приложений Java), решение может быть следующим:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

Пример:

  • GET http://example.com/about
  • Веб-сервер выдает http 404, потому что эта страница не существует на стороне сервера
  • конфигурация страницы ошибки сообщает серверу, который отправляет страницу index.jsp обратно пользователю
  • затем JS выполнит остальную часть работы на стороне клиента, поскольку URL-адрес на стороне клиента все еще http://example.com/about .

Вот и все, больше никаких магических потребностей :)

3
zappee

Если у вас есть запасной вариант для вашего index.html, убедитесь, что в вашем файле index.html есть следующее:

<script>
  System.config({ baseURL: '/' });
</script>

Это может отличаться от проекта к проекту.

2
Matt Goo

Я нашел решение для моего SPA с реагирующим маршрутизатором (Apache). Просто добавьте в .htaccess

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

источник: https://Gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

2
Sasha Ignashevich

Если вы используете firebase, все, что вам нужно сделать, это убедиться, что у вас есть свойство rewrites в файле firebase.json в корне вашего приложения (в разделе хостинга).

Например:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

Надеюсь, что это сэкономит кому-то еще кучу разочарования и потраченного времени.

Удачного кодирования ...

Дальнейшее чтение по теме:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI: "Настроить как одностраничное приложение (переписать все URL в /index.html)"

2
Joshua Dyck

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

Мой основной JSX содержит это:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

Это прекрасно работает для первой подходящей ссылки, но когда: id изменяется в выражениях <Link>, вложенных в страницу сведений об этой модели, URL-адрес изменяется в панели браузера, но содержимое страницы изначально не изменялось, чтобы отражать связанную модель.

Проблема была в том, что я использовал props.params.id, чтобы установить модель в componentDidMount. Компонент монтируется только один раз, так что это означает, что первая модель - это та, которая прикрепляется на странице, а последующие ссылки изменяют реквизиты, но оставляют страницу неизменной.

Установка модели в состояние компонента как в componentDidMount, так и в componentWillReceiveProps (где она основана на следующих подпорках) решает проблему, и содержимое страницы изменяется, отражая желаемую модель.

2
Paul Whipp

Поскольку я использую .Net Core MVC, мне помогло нечто подобное:

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var url = Request.Path + Request.QueryString;
            return App(url);
        }

        [Route("App")]
        public IActionResult App(string url)
        {
            return View("/wwwroot/app/build/index.html");
        }
   }

В основном на стороне MVC все несоответствующие маршруты попадут в Home/Index, как указано в startup.cs. Внутри Index можно получить исходный URL-адрес запроса и передать его, где это необходимо.

startup.cs

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
1
Elnoor

Если вы используете хостинг в IIS; Добавление этого в мой webconfig решило мою проблему

    <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
        <remove statusCode="500" subStatusCode="100" />
        <remove statusCode="500" subStatusCode="-1" />
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
        <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
        <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
    </httpErrors>

Вы можете сделать аналогичную конфигурацию для любого другого сервера

1
Barny

В случае, если здесь кто-то ищет решение в React JS SPA с Laravel. Принятый ответ является лучшим объяснением того, почему возникают такие проблемы. Как уже объяснялось, вы должны настроить как клиентскую, так и серверную сторону. В свой шаблон blade-сервера включите файл js в комплекте, убедитесь, что вы используете URL facade

<script src="{{ URL::to('js/user/spa.js') }}"></script>

В ваших маршрутах обязательно добавьте это к главной конечной точке, где находится шаблон блэйда. Например,

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

Выше приведен основной конечный пункт для шаблона лезвия. Теперь добавьте дополнительный маршрут,

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

Проблема, которая возникает, заключается в том, что сначала загружается шаблон блейда, а затем реагирующий маршрутизатор. Итак, когда вы загружаете '/setting-alerts', он загружает HTML и JS. Но когда вы загружаете '/setting-alerts/about', он сначала загружается на стороне сервера. Поскольку на стороне сервера в этом месте ничего нет, возвращается не найдено. Когда у вас есть этот дополнительный маршрутизатор, он загружает ту же страницу, и загружается реагирующий маршрутизатор, а затем реагирующий загрузчик решает, какой компонент показать. Надеюсь это поможет.

1
Koushik Das

Если вы используете Express или какой-либо другой фреймворк в бэкэнде, вы можете добавить аналогичную конфигурацию, как показано ниже, и проверить открытый путь Webpack в конфигурации, он должен работать нормально даже при перезагрузке, если вы используете BrowserRouter

` expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
  });`
1
user2849063

Добавление дополнительной информации в ответ Джошуа Дейка .

Если вы используете Firebase и хотите использовать как корневой маршрут, так и маршрут подкаталога, вам нужно добавить следующий код в свой firebase.json:

{
  "hosting": {
    "rewrites": [
      {
        "source": "*",
        "destination": "/index.html"
      },
      {
        "source": "/subdirectory/**",
        "destination": "/subdirectory/index.html"
      }
    ]
  }
}

Пример:

Вы создаете сайт для клиента. Вы хотите, чтобы владелец веб-сайта добавил информацию в https://your.domain.com/management , а пользователи веб-сайта перейдут на https: //your.domain. ком .

В этом случае ваш файл firebase.json будет выглядеть так:

{
  "hosting": {
    "rewrites": [
      {
        "source": "*",
        "destination": "/index.html"
      },
      {
        "source": "/management/**",
        "destination": "/management/index.html"
      }
    ]
  }
}
0
neomib

Полный маршрутизатор с примером (React Router v4):

Пример рабочего примера Проверьте проект ниже.

https://github.com/eh3rrera/react-router-4-example

После загрузки
1.) "Npm install" в cmd для установки проекта
2.) "Npm start", чтобы запустить приложение реакции

Примечание: вам нужно программное обеспечение Node js для запуска в ваших окнах. Mac OS имеет узел по умолчанию.

Ура

0
Muthu Kumar

Для тех, кто использует IIS 10, это то, что вы должны сделать, чтобы сделать это правильно. Убедитесь, что вы используете browserHistory с этим. Что касается справки, я дам код для маршрутизации, но это не имеет значения, важен следующий шаг после кода компонента ниже:

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

Поскольку проблема заключается в том, что IIS получает запрос от клиентских браузеров, он будет интерпретировать URL-адрес так, как если бы он запрашивал страницу, а затем возвращает страницу 404, поскольку страница недоступна. Сделайте следующее:

  1. Откройте IIS
  2. Разверните Сервер, затем откройте папку "Сайты".
  3. Нажмите на сайт/приложение
  4. Перейти на страницы ошибок
  5. Откройте пункт состояния ошибки 404 в списке
  6. Вместо опции "Вставить содержимое из статического файла в ответ об ошибке" измените его на "Выполнить URL на этом сайте" и добавьте "/" значение косой черты в URL.

И теперь это будет работать нормально.

enter image description hereenter image description here

Я надеюсь, что это помогает. :-)

0
Martin Lloyd Jose

Я использую WebPack, у меня была такая же проблема Решение => В вашем файле server.js

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

https://github.com/ReactTraining/react-router/blob/master/FAQ.md#why-doesnt-my-application-render-after-refreshing

0
Vishal Singh

У меня была такая же проблема и это решение сработало для нас ..

Фон:

Мы размещаем несколько приложений на одном сервере. Когда мы обновим сервер, он не поймет, где искать наш индекс в папке dist для этого конкретного приложения. Приведенная выше ссылка приведет вас к тому, что сработало для нас ... Надеюсь, это поможет, поскольку мы потратили немало часов, чтобы найти решение для наших нужд.

Мы используем:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

мой webpack.config.js

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

мой index.js

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

мой app.js

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});
0
J. Parrish

Исправление ошибки "невозможно получить/URL" при обновлении или при непосредственном вызове URL.

Сконфигурируйте ваш webpack.config.js так, чтобы ожидать от данной ссылки таких маршрутов.

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
    },
0
Lalit Tyagi

Мне нравится этот способ справиться с этим. Попробуйте добавить: yourSPAPageRoute/* на стороне сервера, чтобы избавиться от этой проблемы.

Я пошел с этим подходом, потому что даже собственный API истории HTML5 не поддерживает правильное перенаправление при обновлении страницы (насколько я знаю).

Примечание. В выбранном ответе это уже учтено, но я пытаюсь быть более конкретным.

Экспресс-маршрут

Test - History API Протестировал и просто хотел этим поделиться.

Надеюсь, поможет.

0
Rehan

Решение для Preact с preact-роутером

Работает с обновлением и прямым доступом

Для тех, кто обнаруживает это через Google, вот демонстрация preact-router + история хешей:

const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
    <div>
        <AddressBar />

        <Router history={createHashHistory()}>
            <div path="/">
                <p>
                    all paths in preact-router are still /normal/urls.
                    using hash history rewrites them to /#/hash/urls
                </p>
                Example: <a href="/page2">page 2</a>
            </div>
            <div path="/page2">
                <p>Page Two</p>
                <a href="/">back to home</a><br/>
            </div>
        </Router>
    </div>
);

https://jsfiddle.net/developit/gLyL6rbn/

0
keemor

Это довольно просто, когда вы не можете получить ошибку 403 после обновления компонента dom. просто добавьте эту строку в конфигурацию вашего веб-пакета, "historyApiFallback: true". это сохранить весь мой день.

0
praveenkumar s