【问题标题】:React Router with deeper paths具有更深路径的 React Router
【发布时间】:2020-05-18 07:23:24
【问题描述】:

我正在尝试运行 React Router 的示例。

我的示例有以下 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(未找到)

主应用类:

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

类名为二:

import * as React from 'react';

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

类名为三:

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/react”:“16.9.11”,
  • "@types/react-dom": "16.9.4",
  • "@types/react-router-dom": "5.1.2",
  • “反应”:“16.11.0”,
  • “react-dom”:“16.11.0”,
  • "react-router-dom": "5.1.2",
  • “打字稿”:“3.7.4”,
  • “webpack”:“4.41.2”,
  • “webpack-cli”:“3.3.10”,
  • “webpack-dev-server”:“3.9.0”

我尝试按照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>;
    }
}

【问题讨论】:

    标签: reactjs typescript routes react-router tsx


    【解决方案1】:

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

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

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

    编辑 2: 您的 404 错误向我表明问题不是路由器而是服务器。您是否构建了服务器,或者 webpack-dev-server 是在您开发时提供服务的预制服务器?我想您会发现,如果您转到 /one 并单击 a 到 /one/two,它实际上会起作用。

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

    按照 cmets 的建议:最终解决方案是在 Webpack 配置中将 publicPath: '/' 添加到 output

    【讨论】:

    • 我尝试按照您的示例进行操作,但没有成功。我在 Edit 2 中更新了上面的帖子。
    • 感谢您的反馈!当您尝试每种解决方案时,有什么变化吗?喜欢哪条路线有效?
    • 是的,我尝试了上面帖子中提到的所有解决方案。 Web 应用程序使用 Webpack 运行。我需要告诉webpack-dev-server 我使用的是 React 路由器吗?
    • 您的 404 错误向我表明问题不是路由器而是服务器。您是否构建了服务器,或者 webpack-dev-server 是在您开发时提供服务的预制服务器?我想您会发现,如果您转到 /one 并单击 到 /one/two,它实际上会起作用。
    • 太棒了,您的路由器可以正常工作。你的 webpack 开发服务器配置需要一些东西。我没有这方面的经验,但这是我认为应该有帮助的文档webpack.js.org/configuration/output/#outputpublicpath。尝试将公共路径设为“/”或“”。
    【解决方案2】:

    尝试在您的&lt;Route/&gt;中使用exact

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

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

    这是docs的链接

    【讨论】:

    • 我尝试按照您的示例进行操作,但没有成功。我在 Edit 1 中更新了上面的帖子。
    猜你喜欢
    • 2019-12-25
    • 2018-12-23
    • 2022-07-21
    • 1970-01-01
    • 2019-11-19
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    相关资源
    最近更新 更多