最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Router URL Throws Error With Parameter - Stack Overflow

programmeradmin2浏览0评论

I am trying to use react router to have dynamic profile pages, preferably having it in slashes rather than like a ? parameter wildcard in the URL. I'm looking for like /profile/{username}/ rather than /profile?user={username} if that makes sense.

Here's the route that I'm using to try and achieve this;

<Route path="/profile/:name/" ponent={Profile}/>

But when I try and go to this route as in `/profile/jeff/' or anything it returns a bundle.js (webpack'd) that is a blank HTML template, which is unexpected to be in the bundle.js and throws an error. Any idea's how I can fix this? Thanks.

Here is the bundle.js that gets returned;

<html>
<body style="margin:0px; padding: 0px;">
    <link rel="stylesheet" href="styles.css">
    <link href="" rel="stylesheet">
    <div id = "root" style="margin:0px; padding: 0px;"></div>
    <script src="bundle.js"></script>
</body>

Profile ponent;

import React from 'react';
import styles from './profile.scss';
import astyles from './allpages.scss';

export default class Profile extends React.Component{
render(){

    console.log("hello!");

    const { match, location, history } = this.props

    console.log(location);
    console.log(match);
    console.log(history);

    return(
        <div className = {styles.borderContainer}>
            <p> {this.props.param.name} </p>
        </div>
    )
}
}

Webpack config;

var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');
require('style-loader');
require('css-loader');

const loaders = {
    css: {
        loader: 'css-loader'
    },
    postcss: {
        loader: 'postcss-loader',
        options: {
            plugins: (loader) => [
                autoprefixer({
                    browsers: ['last 2 versions']
                })
            ]
        }
    },
    sass: {
        loader: 'sass-loader',
        options: {
            indentedSyntax: true,
            includePaths: [path.resolve(__dirname, './src/app')]
        }
    }
}


module.exports = {
    context: __dirname,
    entry: './src/app/index.js',
    output: {
        path: __dirname + '/dist/',
        filename: 'bundle.js',
        libraryTarget: 'umd'
    },
    devtool: "sourceMap",
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',

                    // Could also be write as follow:
                    // use: 'css-loader?modules&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader'
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                localIdentName: '[name]__[local]___[hash:base64:5]'
                            }
                        },
                        'postcss-loader'
                    ]
                }),
            },
            {
                test: /\.scss$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',

                    // Could also be write as follow:
                    // use: 'css-loader?modules&importLoader=2&sourceMap&localIdentName=[name]__[local]___[hash:base64:5]!sass-loader'
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                sourceMap: true,
                                importLoaders: 2,
                                localIdentName: '[name]__[local]___[hash:base64:5]'
                            }
                        },
                        'sass-loader'
                    ]
                }),
            },
        ],
    },
    plugins: [
        new ExtractTextPlugin('styles.css'),
    ],
}

I am trying to use react router to have dynamic profile pages, preferably having it in slashes rather than like a ? parameter wildcard in the URL. I'm looking for like /profile/{username}/ rather than /profile?user={username} if that makes sense.

Here's the route that I'm using to try and achieve this;

<Route path="/profile/:name/" ponent={Profile}/>

But when I try and go to this route as in `/profile/jeff/' or anything it returns a bundle.js (webpack'd) that is a blank HTML template, which is unexpected to be in the bundle.js and throws an error. Any idea's how I can fix this? Thanks.

Here is the bundle.js that gets returned;

<html>
<body style="margin:0px; padding: 0px;">
    <link rel="stylesheet" href="styles.css">
    <link href="https://fonts.googleapis./css?family=Ubuntu" rel="stylesheet">
    <div id = "root" style="margin:0px; padding: 0px;"></div>
    <script src="bundle.js"></script>
</body>

Profile ponent;

import React from 'react';
import styles from './profile.scss';
import astyles from './allpages.scss';

export default class Profile extends React.Component{
render(){

    console.log("hello!");

    const { match, location, history } = this.props

    console.log(location);
    console.log(match);
    console.log(history);

    return(
        <div className = {styles.borderContainer}>
            <p> {this.props.param.name} </p>
        </div>
    )
}
}

Webpack config;

var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');
require('style-loader');
require('css-loader');

const loaders = {
    css: {
        loader: 'css-loader'
    },
    postcss: {
        loader: 'postcss-loader',
        options: {
            plugins: (loader) => [
                autoprefixer({
                    browsers: ['last 2 versions']
                })
            ]
        }
    },
    sass: {
        loader: 'sass-loader',
        options: {
            indentedSyntax: true,
            includePaths: [path.resolve(__dirname, './src/app')]
        }
    }
}


module.exports = {
    context: __dirname,
    entry: './src/app/index.js',
    output: {
        path: __dirname + '/dist/',
        filename: 'bundle.js',
        libraryTarget: 'umd'
    },
    devtool: "sourceMap",
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',

                    // Could also be write as follow:
                    // use: 'css-loader?modules&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader'
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                localIdentName: '[name]__[local]___[hash:base64:5]'
                            }
                        },
                        'postcss-loader'
                    ]
                }),
            },
            {
                test: /\.scss$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',

                    // Could also be write as follow:
                    // use: 'css-loader?modules&importLoader=2&sourceMap&localIdentName=[name]__[local]___[hash:base64:5]!sass-loader'
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                sourceMap: true,
                                importLoaders: 2,
                                localIdentName: '[name]__[local]___[hash:base64:5]'
                            }
                        },
                        'sass-loader'
                    ]
                }),
            },
        ],
    },
    plugins: [
        new ExtractTextPlugin('styles.css'),
    ],
}
Share Improve this question edited Nov 14, 2017 at 18:19 Michael Jungo 33.1k4 gold badges95 silver badges87 bronze badges asked Nov 14, 2017 at 17:52 Intoxicated PenguinIntoxicated Penguin 3644 silver badges18 bronze badges 7
  • Please share the error – Dhaval Jardosh Commented Nov 14, 2017 at 17:55
  • Uncaught SyntaxError: Unexpected token < – Intoxicated Penguin Commented Nov 14, 2017 at 18:00
  • Can you share the Profile ponent code? – Maluen Commented Nov 14, 2017 at 18:04
  • can you share webpack.config.js ? – Aaqib Commented Nov 14, 2017 at 18:10
  • I added both webpack.config.js & the profile ponent. – Intoxicated Penguin Commented Nov 14, 2017 at 18:15
 |  Show 2 more ments

3 Answers 3

Reset to default 6

When you request /profile/jeff/ you serve the index.html you posted, and presumably that is done for every resource that doesn't exist on your server (as a fallback). In the index.html you have the following script tag:

<script src="bundle.js"></script>

This is a relative path. You are actually requesting /profile/jeff/bundle.js at this point and because that doesn't exist, you end up serving the index.html as the bundle, which is problematic because it's not valid JavaScript.

You should always use /bundle.js regardless of the current URL. Similarly you'd always want /styles.css for your CSS.

<link rel="stylesheet" href="/styles.css">
<script src="/bundle.js"></script>

I don't have a better source for this, but the development server needs to be configured to handle React Routers dynamic routes because it should always serve the same html file (index.html) because it's an SPA.

https://redux.js/docs/advanced/UsageWithReactRouter.html

Edit:

Particularly, I think you are missing this in your webpack config

devServer: {
  historyApiFallback: true
}

Edit 2:

For ExpressJS you would need something like this,

app.get('/*', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'))
})

It looks like it's your stylesheet inclusion. My understanding is that you should be using a babel import statement in your ponent, not link tags, or they will 404 causing the error you are seeing.

发布评论

评论列表(0)

  1. 暂无评论