2

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/" component={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.com/css?family=Ubuntu" rel="stylesheet">
    <div id = "root" style="margin:0px; padding: 0px;"></div>
    <script src="bundle.js"></script>
</body>

Profile component;

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'),
    ],
}
7
  • Please share the error Commented Nov 14, 2017 at 17:55
  • Uncaught SyntaxError: Unexpected token < Commented Nov 14, 2017 at 18:00
  • Can you share the Profile component code? Commented Nov 14, 2017 at 18:04
  • can you share webpack.config.js ? Commented Nov 14, 2017 at 18:10
  • I added both webpack.config.js & the profile component. Commented Nov 14, 2017 at 18:15

3 Answers 3

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>
Sign up to request clarification or add additional context in comments.

2 Comments

That was my problem. Thank you!
I wish I could give more than 1 up vote. I was banging my head, as why are my urls not working. Thank you so much.
1

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.org/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'))
})

3 Comments

I should add this only applies if you are serving your App with WebpackDevServer, but I believe that is the case here.
Not serving with the webpackdevserver. This specific route causes the contents of bundle.js to be the same as index.html for some reason. Other routes to other components do not do this, and the bundle.js is what it is expected to be and loads fine.
I have that exact statement in express - other routes work just fine. This particular one does not when I have the parameter built into the route.
0

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

1 Comment

That stylesheet inclusion works fine in other components.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.