React Router способен выполнять маршрутизацию только при запуске с корневого url-адреса
У меня есть приложение React, которое также использует Redux и ReactRouter.
Моя проблема заключается в следующем:
Когда я запускаю приложение и иду к корневому url, я обычно могу перемещаться внутри приложения, и маршруты в навигационной панели будут меняться по мере перемещения.
Однако, если я наберу в навигационной панели любой url, отличный от корневого, я получу странную ошибку:


Я действительно не понимаю, как можно получить такую ошибку.
Если я пойду для localhost:1337/, а затем нажмите на элемент со ссылкой /cars/1, все будет хорошо, и компонент будет успешно отрисован. Если я наберу localhost:1337/cars/1 сразу (или любой другой существующий маршрут), я получу эту ошибку.
Вот как я инициализирую react-маршрутизатор и определяю свои маршруты:
Индекс.js:
require('./style/style.css');
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reduxPromise from 'redux-promise';
import routes from './routes';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(
reduxPromise
)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory} routes={routes} />
</Provider>
, document.querySelector('.container.app')
);
Маршруты.js:
import React from 'react';
import { Route, IndexRoute, Redirect } from 'react-router';
import App from './components/app';
import CarsIndex from './containers/cars-index';
import CarNew from './containers/car-new';
import CarShow from './containers/car-show';
import CarEdit from './containers/car-edit';
import SignIn from './containers/signin';
import auth from './auth/auth';
function requireAuth(nextState, replace) {
if (!auth.loggedIn()) {
replace({
pathname: '/authenticate',
state: { nextPathname: nextState.location.pathname }
});
}
}
function filterLoggedIn(nextState, replace) {
if (auth.loggedIn()) {
replace({
pathname: '/',
state: { nextPathname: nextState.location.pathname }
});
}
}
export default (
<Route path='/' component={App}>
<IndexRoute component={CarsIndex} onEnter={requireAuth} />
<Route path='cars/new' component={CarNew} onEnter={requireAuth} />
<Route path='cars/:id' component={CarShow} onEnter={requireAuth} />
<Route path='cars/edit/:id' component={CarEdit} onEnter={requireAuth} />
<Route path='authenticate' component={SignIn} onEnter={filterLoggedIn} />
<Redirect from='*' to='/' />
</Route>
);
Мой сервер-это маленький экспресс.JS приложение и перенаправляет любые запросы, кроме /api/* на страницу index.html.
Вот часть из мой server.js:
const path = require('path');
const port = process.env.PORT || 1337;
const app = express();
const pathToStatic = path.join(__dirname, 'static');
express.static(path.join(__dirname, 'static'));
app.use(express.static(pathToStatic));
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.get('/api/cars', (req, res) => {
return Car.find((err, cars) => {
if (!err) {
return res.send(cars);
} else {
console.log(err);
res.statusCode = 500;
return res.send({ error: 'Server error' });
}
});
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(pathToStatic, 'index.html'));
});
app.listen(port, () => {
console.log(`Express server is listening on port ${port}`);
});
Сталкивались ли вы с такой проблемой? Не могли бы вы помочь мне найти ответ на этот вопрос?
1 ответ:
Скриншот показывает, что
bundle.js(при запросе) возвращаетindex.html.Это потому, что ваши экспресс-маршруты обрабатывают маршрут
api/cars, а затем по умолчанию все остальное индексировать.формат html.Конечно, все ваши ресурсы, которые появляются на
index.html, также должны быть отправлены браузеру. Это включает в себя<script src="bundle.js"></script>, который браузер запросит, как только он получитindex.htmlв первый раз.Итак, у вас должен быть какой-то способ разрешить express обрабатывать запросы на ресурсы, которые
index.htmlпотребности.Популярным решением для этого являетсямонтирование каталога активов и размещение его над маршрутом по умолчанию. Что-то вроде:
// api routes app.use(express.static('assets')); // default routeЗатем убедитесь, что ваш
bundle.jsнаходится в каталоге активов. И затем, что тег сценария выглядит как<script src="/assets/bundle.js"></script>.
Comments