React Router с более глубокими путями - PullRequest
0 голосов
/ 02 февраля 2020

Я пытаюсь получить пример с запущенным React Router.

В моем примере есть 3 следующих маршрута:

  1. (работает в браузере) http://0.0.0.0: 8081 / один
  2. (ошибка в браузере) http://0.0.0.0: 8081 / один / два
  3. (ошибка в браузере) http://0.0.0.0: 8081 / один / два / три

Все маршруты работают с Link, но только 1. работает при наборе URL в браузере. При наборе, например, 2. маршрута в браузере, консоль браузера выдает следующую ошибку:

GET http://0.0.0.0: 8081 / one / app. js net :: ERR_ABORTED 404 (не найден)

Основной класс приложения:

import * as React from 'react';
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';
import { One } from './One';
import { Two } from './Two';
import { Three } from './Three';

export class App2 extends React.Component<{}, {}> {
    public render() {
        return <BrowserRouter>
            <ul>
                <li>
                    <Link to='/one'>One</Link>
                </li>
                <li>
                    <Link to='/one/two'>Two</Link>
                </li>
                <li>
                    <Link to='/one/two/three'>Three</Link>
                </li>
            </ul>
            <Switch>
                <Route path='/one/two/three' component={Three} />
                <Route path='/one/two' component={Two} />
                <Route path='/one' component={One} />
            </Switch>
        </BrowserRouter>;
    }
}

Класс с именем One:

import * as React from 'react';

export class One extends React.Component<{}, {}> {
    public render() {
        return <div>One</div>;
    }
}

Класс с именем Two:

import * as React from 'react';

export class Two extends React.Component<{}, {}> {
    public render() {
        return <div>Two</div>;
    }
}

Класс с именем Three:

import * as React from 'react';

export class Three extends React.Component<{}, {}> {
    public render() {
        return <div>Three</div>;
    }
}

Команда для запуска приложения в режиме разработки:

"scripts": {
    "develop": "webpack-dev-server --mode development --open --port 8081 --host 0.0.0.0 --config webpack.dev.config.js"
}

Конфигурация Webpack webpack.dev.config. js:

const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const htmlPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "./index.html"
});

module.exports = {
    entry: "./src/index.tsx",
    output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist")
    },

    // Enable sourcemaps for debuggin webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts', and '.tsx' as resolvable exteensions.
        extensions: [".ts", ".tsx", ".js", ".json"]
    },

    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },

            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

            {
                test: /\.css$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "typings-for-css-module-loader", options: { modules: true, namedExport: true, camelCase: true, localIdentName: "[name]_[local]_[hash:base64]" }}
                ]
            },

            {
                test: /\.scss$/,
                exclude: /\.global.scss$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "typings-for-css-modules-loader", options: { modules: true, namedExport: true, camelCase: true, localIdentName: "[local]" }},
                    { loader: "postcss-loader", options: { plugins: function () { return [ require("autoprefixer") ]; }}},
                    { loader: "sass-loader" }
                ]
            },

            {
                test: /\.scss$/,
                include: /\.global.scss$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" },
                    { loader: "postcss-loader", options: { plugins: function () { return [ require("autoprefixer") ]; }}},
                    { loader: "sass-loader" }
                ]
            }
        ]
    },

    devServer: {
        historyApiFallback: true,
        disableHostCheck: true
    },

    plugins: [
        new CleanWebpackPlugin({
            cleanAfterEveryBuildPatterns: ['dist']
        }),
        htmlPlugin
    ]
};

Я использую следующие версии:

  • Узел v13.7.0
  • "@ types / реагировать": "16.9.11",
  • "@ types / response-dom": "16.9.4",
  • "@ types / response-router-dom": "5.1.2",
  • " реагировать ":" 16.11.0 ",
  • " реагировать-дом ":" 16.11.0 ",
  • " реагировать-маршрутизатор-дом ":" 5.1.2 ",
  • "машинопись": "3.7.4",
  • "webpack": "4.41.2",
  • "webpack-cli": "3.3.10",
  • "webpack-dev-server": "3.9.0"

Я пытался следовать примерам he re .

Почему работает только 1. маршрут? Почему другие маршруты 2. и 3. не работают?

Редактировать 1:

Попытка использовать точное тоже не работает. Результат такой же, как указано выше:

import * as React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { One } from './One';
import { Two } from './Two';
import { Three } from './Three';

export class App2 extends React.Component<{}, {}> {
    public render() {
        return <BrowserRouter>
            <Switch>
                <Route exact path='/one' component={One} />
                <Route exact path='/one/two' component={Two} />
                <Route exact path='/one/two/three' component={Three} />
            </Switch>
        </BrowserRouter>;
    }
}

Edit 2:

Попытка изменить порядок также не работает. Результат такой же, как указано выше:

import * as React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { One } from './One';
import { Two } from './Two';
import { Three } from './Three';

export class App2 extends React.Component<{}, {}> {
    public render() {
        return <BrowserRouter>
            <Switch>
                <Route path='/one/two/three' component={Three} />
                <Route path='/one/two' component={Two} />
                <Route path='/one' component={One} />
            </Switch>
        </BrowserRouter>;
    }
}

Ответы [ 2 ]

2 голосов
/ 02 февраля 2020

Проще: самый конкретный c маршрут идет первым. Просто измените порядок.

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

Редактировать 1: свидетельство https://reacttraining.com/react-router/web/guides/primary-components

Редактировать 2: Ваша ошибка 404 указывает мне, что проблема не в маршрутизаторе, а в сервере. Вы собрали сервер или webpack-dev-server является готовым сервером для обслуживания во время разработки? Я думаю, вы обнаружите, что если вы go to / one и нажмете a to / one / two, то это на самом деле будет работать.

Edit 3: Конфигурация вашего сервера Dev Webpack требует чего-то , У меня нет опыта с этим, но вот do c webpack. js .org / configuration / output / # outputpublicpath, который, я думаю, должен помочь.

Как предлагается в комментариях : Окончательное решение - добавить publicPath: '/' к output в конфигурации Webpack.

1 голос
/ 02 февраля 2020

Попробуйте использовать точно в вашем <Route/>

Поскольку ваши пути всегда начинаются с /one, реагирующий маршрутизатор соответствует только этой части, если вы хотите go глубже, вы должен сказать ему точно (ли), что вы хотите.

<Route exact path='/one' component={One} />
<Route exact path='/one/two' component={Two} />
<Route exact path='/one/two/three' component={Three} />

Вот ссылка на документы

...