刷新时无法对GET / currentSite做出反应

时间:2017-09-08 08:58:26

标签: javascript reactjs browser webpack react-router

我有问题。我无法刷新我的反应组件/页面而没有“无法获取/当前页面”。我已经浏览了你一段时间,发现了一些可以解决我问题的链接:

https://github.com/jintoppy/react-training/blob/master/basic/node_modules/react-router/docs/guides/Histories.md#browserhistory

BrowserHistory的HashHistory。互联网说我应该使用BrowserHistory进行制作 - 但是hashHistory更容易。它们都非常复杂。我不知道如何将它实现到我当前的代码中。

这是我的app.js文件:

/*global $:true*/

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import './scss/app.scss';

// Component imports
import Home from './components/home';
import Archive from './archive';

// Image import
import loadImg from './images/tits.gif';

class App extends Component {

  // Function for anchorlinks
  hashLinkScroll() {
    const { hash } = window.location;
    if (hash !== '') {
      // Push onto callback queue so it runs after the DOM is updated, this is required when navigating from a different page so that the element is rendered on the page before trying to getElementById
      setTimeout(() => {
        const id = hash.replace('#', '');
        const element = document.getElementById(id);
        if (element) element.scrollIntoView();
      }, 100);
    }
  }

  // 1. Render site-loader gif
  // 2. React Router component wraps all of the routes we are going to define - Archive and Home. Each route will be identified in a <Route> component. The <Route> component will take two properties: path and component. When a path matches the path given to the <Route> component, it will return the component specified.
  render() {
    return (
      <div>
        <div className="loaderSmall">
          <img className="loadingImg" src={loadImg} width="400"/>
        </div>
        <Router history={browserHistory} onUpdate={this.hashLinkScroll}>
          <Route path={'/archive'} component={Archive} />
          <Route path={'*'} component={Home} />
        </Router>
      </div>
    );
  };

  // When Component has rendered, window.addEventListener adds event "load" and calls handleLoad function
  componentDidMount() {
    window.addEventListener('load', this.handleLoad);
  }

  // Fade out site-loader
  handleLoad() {
    $(".loaderSmall").delay(500).fadeOut("slow");
  }
};

ReactDOM.render (
  <App/>,
  document.getElementById('app')
)

// Hot Module Replacement API (injecting code)
if (module.hot) {
    module.hot.accept();
}

export default App;

..这是我的菜单组件,当我在“/ archive”组件上时呈现:

import React, { Component } from 'react';
import { Link } from 'react-router';

//Menu component renders menu Link
class Menu extends Component {
  render() {
    return (
      <header>
        <nav>
          <ul>
            <li><Link to={'/#top'}>Home</Link></li>
            <li><Link to={'/#about'}>About</Link></li>
            <li><Link to={'/archive'}>Archive</Link></li>
            <li className="contactMobile"><a href="mailto:magdamargaretha@gmail.com?Subject=magdenmagden">Contact</a></li>
            <li className="contactWeb"><Link to={'/#contact'}>Contact</Link></li>
          </ul>
        </nav>
      </header>
    );
  }
}

export default Menu;

..这是我的另一个菜单,当我在root上我想要可滚动的hashlinks时呈现:

import React, { Component } from 'react';
import { Link } from 'react-router';
import Scrollchor from 'react-scrollchor';

//Menu component renders menu Link
class MenuB extends Component {
  render() {
    return (
      <header>
        <nav>
          <ul>
            <li><Scrollchor to="#top" animate={{offset: 20, duration: 800}}>Home</Scrollchor></li>
            <li><Scrollchor to="#about" animate={{offset: 0, duration: 800}}>About</Scrollchor></li>
            <li><Link to={'/archive'}>Archive</Link></li>
            <li className="contactMobile"><a href="mailto:magdamargaretha@gmail.com?Subject=magdenmagden">Contact</a></li>
            <li className="contactWeb"><Scrollchor to="#contact" animate={{offset: 20, duration: 800}}>Contact</Scrollchor></li>
          </ul>
        </nav>
      </header>
    );
  }
}

export default MenuB;

我的webpack.config.js文件:

// DEVELOPMENT

const webpack = require('webpack');
const path = require('path');

const entry = [
    'webpack-dev-server/client?http://localhost:8080', // bundle the client for webpack-dev-server and connect to the provided endpoint
    'webpack/hot/only-dev-server', // bundle the client for hot reloading only- means to only hot reload for successful updates
    './app.js'
]

const output = {
    path: path.join(__dirname, 'dist'),
    publicPath: '/dist',
  filename: 'bundle.min.js'
}

const plugins = [
    new webpack.HotModuleReplacementPlugin(), // enable HMR globally
    new webpack.NamedModulesPlugin() // prints more readable module names in the browser console on HMR updates
]

const config = {
  context: path.join(__dirname, 'src'),
  entry: entry,
    output: output,
    devtool: "inline-source-map",
  module: {
    rules: [
            {
                // test: /\.(js|jsx)$/,
                // exclude: /node_modules/,
                // include: path.join(__dirname, 'src'),
                // use: {
                //  loader: "eslint-loader",
                //  options: {
          //     failOnWarning: false,
          //     failOnError: false
                //  }
                // }
        },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: path.join(__dirname, 'src'),
                use: {
                    loader: "babel-loader"
                }
            },
      {
              test: /\.(png|jpg|gif)$/,
              use: [{
                loader: 'url-loader',
          options: { limit: 10000, name: './images/[name].[ext]' }
              }]
            },
            {
                test: /\.(sass|scss)$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            }
        ]
  },
    performance: {
        maxAssetSize: 400000000,
        maxEntrypointSize: 400000000,
        hints: 'warning'
    },
    plugins: plugins,
    externals: {
      jquery: 'jQuery'
    }
}

module.exports = config

我的webpack.config.prod.js文件:

//  PRODUCTION

const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const entry = {
    app: path.join(process.cwd(), 'src/app.js')
}

const output = {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.min.js',
}

const plugins = [
    new webpack.DefinePlugin({
      // 'process.env.NODE_ENV': JSON.stringify('production')
        'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
        mangle: false,
        compress: {
            warnings: false
        }
    }),
  new ExtractTextPlugin('bundle.css'), // creation of HTML files to serve your webpack bundles
    new HtmlWebpackPlugin({
        template: 'index-template.html'
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'bundle',
        filename: '[name].common.js'
    })
]

const config = {
  context: path.join(__dirname, 'src'),
  entry: entry,
    output: output,
    devtool: "source-map",
  module: {
    rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                include: path.join(__dirname, 'src'),
                use: "babel-loader"
            },
      {
              test: /\.(png|jpg|gif)$/,
              use: [{
                    loader: 'url-loader',
                    options: { limit: 10000, name: './images/[name].[ext]' } // Convert images < 10k to base64 strings (all in images folder)
                }]
            },
            {
                test: /\.(sass|scss)$/,
                use: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: [
                  'css-loader',
                  {
                            loader: 'postcss-loader',
                            options: {
                                plugins: (loader) => [ require('autoprefixer')() ]
                            }
                        },
                  'sass-loader',
                ]
              })
            }
        ]
  },
    plugins: plugins,
    externals: {
      jquery: 'jQuery'
    }
}

module.exports = config;

..我知道有更好的方法来做到这一点,而不是让两个菜单组件在不同的页面上呈现,但我现在只是做了这个解决方案。问题是我不知道如何转换这个到了BrowserHistory的HashHistory而没有失去我的逻辑。任何提示/输入都会非常感激,并且已经持续了好几个星期&lt; 3

2 个答案:

答案 0 :(得分:0)

  

无法GET / currentPage?

对于页面刷新时的browserHistory,在服务器端请求/currentPage

在后端,您的服务器没有定义此路径(请求的资源)。

您需要将其实施为固定Cannot GET问题以进行页面刷新。

假设nodejs

app.use(express.static(__dirname));

//will serve index.html for every page refresh.
app.use('*',(req,resp)=>{
    res.sendFile(path.resolve(__dirname+'/index.html')) 
})

app.listen(someport)

这将为每次刷新页面加载index.html页面。

一旦index.html加载了所需的JS&amp;反应路由器,

路由器将触发路由,并且相应的组件将被渲染。

答案 1 :(得分:0)

@Panther解决了这个问题。为了能够在我的开发环境中刷新页面,我不得不添加:

historyApiFallback: {
   disableDotRule: true
}

到我的webpack dev.server文件:

var WebpackDevServer = require('webpack-dev-server');
var webpack = require('webpack');
// requiring my webpack configuration
var config = require('./webpack.config.js');
var path = require('path');

var compiler = webpack(config);
// then spinning up a new dev server with some settings
var server = new WebpackDevServer(compiler, {
    hot: true,
    filename: config.output.filename,
    publicPath: config.output.publicPath,
    proxy: {
        "/getMail": 'http://localhost:80/magdan/php/mailer.php',
        "/getProducts": 'http://localhost:80/magdan/php/products.php'
    },
    stats: {
        colors: true
    },
    historyApiFallback: {
      disableDotRule: true
    }
});

// its gonna listen to port 8080
server.listen(8080, 'localhost', function() {
    console.log("Starting server on http://localhost:8080");
});