具有更深路径的 React Router

React Router with deeper paths

我正在尝试使用 React Router 运行ning 获取示例。

我的示例有以下 3 条路线:

  1. (在浏览器中工作)http://0.0.0.0:8081/one
  2. (在浏览器中失败)http://0.0.0.0:8081/one/two
  3. (在浏览器中失败)http://0.0.0.0:8081/one/two/three

所有路由都适用于 Link,但只有 1. 在浏览器中键入 url 时有效。在浏览器中输入即 2. 路由时,浏览器控制台响应以下错误:

GET http://0.0.0.0:8081/one/app.js net::ERR_ABORTED 404 (Not Found)

主应用 class:

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

Class 名为一:

import * as React from 'react';

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

Class 名为二:

import * as React from 'react';

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

Class 名为三:

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
    ]
};

我使用以下版本:

我尝试按照示例进行操作 here

为什么只有 1. 路由有效?为什么其他路线 2. 和 3. 不工作?

编辑 1:

尝试使用 exact 也不起作用。结果同上:

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

编辑 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>;
    }
}

简单地说:最具体的路线先行。只需取消您的订单即可。

与大多数路由器一样,每个路由器都按顺序检查是否匹配。

编辑 1: 证据 https://reacttraining.com/react-router/web/guides/primary-components

编辑 2: 你的 404 错误告诉我问题不是路由器而是服务器。您是构建服务器还是 webpack-dev-server 是在您开发时用于服务的预制服务器?我想您会发现,如果您转到 /one 并单击 /one/two,它实际上会起作用。

编辑 3: 您的 webpack 开发服务器配置需要一些东西。我没有这方面的经验,但这里有一个文档 webpack.js.org/configuration/output/#outputpublicpath 我认为应该有所帮助。

如评论中所建议:最终解决方案是在 Webpack 配置中将 publicPath: '/' 添加到 output

尝试在 <Route/>

中使用 exact

因为你的路径总是以/one开头,react router只匹配那部分,如果你想更深入,你必须告诉他exact(ly) what你要。

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

这是 link 到 docs