【问题标题】:react-router-redux webpack dev server historyApiFallback failsreact-router-redux webpack 开发服务器 historyApiFallback 失败
【发布时间】:2016-09-15 08:31:12
【问题描述】:

在 webpack 配置文件中启用 historyApiFallback 并重启服务器后,当更改位置路径名时,浏览器刷新,导致外部元素重新挂载(我的意思是,我可以看到它闪烁白色并恢复正常)这应该只发生在嵌套的the.props.children

在我的特定情况下,有一个始终位于顶部的<Navbar /> 元素和一个具有{ this.props.children } 的容器。我想知道这是怎么回事?

应用入口点:

import React from 'react';
import ReactDOM from "react-dom";
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import { syncHistoryWithStore } from 'react-router-redux'
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import promise from 'redux-promise';
import reducers from './reducers';
import thunk from 'redux-thunk';

// const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
// const store = createStoreWithMiddleware(reducers);
const store = createStore(
    reducers,
    applyMiddleware(thunk)
);
const history = syncHistoryWithStore(browserHistory, store);

ReactDOM.render(
    <Provider store={ store }>
        <Router history={ history } routes={ routes } />
    </Provider>,
    document.getElementById('app')
);

webpack 配置文件:

var path = require("path");
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    historyApiFallback: true,
    entry: [
        'webpack-dev-server/client?http://localhost:3000',
        'webpack/hot/dev-server',
        './src/js/index.js'
    ],
    output: {
        path: __dirname + '/static',
        filename: "index_bundle.js"
    },
    module: {
        loaders: [
            { test: /\.js$/, exclude: /node_modules/, loaders: ["react-hot-loader", "babel-loader"] },
            { test: /\.scss$/, loader: 'style!css!sass' },
            { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, loader: 'file-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: __dirname + '/src/' + 'index.html',
            filename: 'index.html'
        }),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin()
    ],
    resolve: {
        root: path.resolve(__dirname),
        extensions: ['', '.js'],
        alias: {
            "TweenLite": "src/libs/gsap/TweenLite",
            "CSSPlugin": "src/libs/gsap/plugins/CSSPlugin"
        }
    }
};

主包装器/容器:

import React, { Component } from 'react';
import Navbar from '../containers/navbar';
import ModalWindow from '../components/modalWindow';

// include the stylesheet entry point
require('../../sass/app.scss');

class App extends Component {
    render() {
        return (
            <div className="app">
                <Navbar />
                <main>
                { this.props.children }
                </main>
                <ModalWindow />
            </div>
        );
    }
}

export default App;

路由器配置文件:

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './containers/app';
import InitialScreen from './containers/initialScreen';
import Reservation from './containers/reservation';

const routes = (
    <Route path='/' component={ App }>
        <IndexRoute component={ InitialScreen } />
        <Route path='your-trolley' component={ Reservation } />           
    </Route>
);

export default routes;

到目前为止,我认为 webpack 开发配置文件有问题。

更新

随机用户询问位置如何更改,因此操作如下:

export function fetchReservationData(reservation_code, onError) {

    return (dispatch) => {
        fetch(apiConfig.find_my_product)
            .then(function(response) {

                if (response.ok) {

                    response.json().then(function (data) {
                        if (data.trolley.length > 0) {
                            dispatch({ type: UPDATE_TROLLEY_DATA, payload: data });
                            // todo: use router-redux push instead
                            window.location.pathname = '/your-trolley';

                        } else {
                            dispatch({ type: TOGGLE_MODAL_WINDOW, payload: onError });                          
                        }
                    });

                } else {

                    // todo: handle exception
                    console.log('Network response was not ok.');
                    dispatch({ type: TOGGLE_MODAL_WINDOW, payload: onError });

                }

            })
            .catch(function (error) {

                // todo: handle error
                // handle it gracefully asked user to try again, if the problem keeps ocurring to
                // talk with a staff member to report it to the backend team
                console.log('There has been a problem with your fetch operation: ' + error.message);
                dispatch({ type: TOGGLE_MODAL_WINDOW, payload: onError });

            });
    }

}

这就是问题所在;如果我更改应用程序入口点,它会起作用:

import React from 'react';
import ReactDOM from "react-dom";
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import { syncHistoryWithStore, routerMiddleware, push } from 'react-router-redux'
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import promise from 'redux-promise';
import reducers from './reducers';
import thunk from 'redux-thunk';

// const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
// const store = createStoreWithMiddleware(reducers);
const store = createStore(
    reducers,
    applyMiddleware(thunk),
    applyMiddleware(routerMiddleware(browserHistory))
);
const history = syncHistoryWithStore(browserHistory, store);

setTimeout(() => {
    store.dispatch(push('/your-trolley'));
}, 3000);

ReactDOM.render(
    <Provider store={ store }>
        <Router history={ history } routes={ routes } />
    </Provider>,
    document.getElementById('app')
);

所以现在我需要能够像在入口点中那样从操作中分派推送。这有点令人困惑,因为我正在将中间件粘贴到商店,然后商店与浏览器历史记录同步,我想我需要在两种情况下(createstore 和 sunchistorywithstore)都从 applyMiddleware(routerMiddleware(browserHistory)) 传递返回值)?

【问题讨论】:

  • 我对@9​​87654330@ 了解不多,但您可以尝试从Route path='/your-trolley' 中删除/ .. 它看起来像Route path='your-trolley' 并看到它有帮助。
  • 感谢收看!我试过了,但不幸的是它仍然无法正常工作。
  • 您是使用a 还是Link from react-router 在页面之间切换? location path怎么改?
  • 我是通过更改 window.location.pathname 来实现的,尝试在应用程序入口点设置超时,在应用 routerMiddleWare 之后,它工作正常!谢谢!我会试着弄清楚如何用这个修改syncHistoryWithStore。
  • 你可以做的是import { browserHistory } from 'react-router';,在你超时的时候,调用browserHistory.push('/path/to/url);而不是window.location.pathname

标签: reactjs webpack redux webpack-dev-server react-router-redux


【解决方案1】:

由于您使用react-router,并且不希望每次切换到新网址时浏览器都重新加载整个页面,因此使用@987654323提供的&lt;Link&gt;组件很重要@ 或创建您自己的组件版本。

要链接不同的页面,你可以

import { Link } from 'react-router';

然后你在你的 render 函数中,像使用它一样使用它

<Link to="/user/profile">Goto Profile Page</Link>
<Link to="/">Homepage</Link>

如果您想以编程方式将用户重定向到不同的网址/位置

import { browserHistory } from 'react-router';

let doSomething = () => {
  // do something
  browserHistory.push('/user/profile');
}

编辑:如果你想使用react-router-redux提供的push方法重定向,你可以这样做

// import push from react-router-redux
import { push } from 'react-router-redux';

// when props.redirect is called, dispatch the push method
const mapDispatchToProps = ( dispatch, ownProps ) => {
  return {
    goto: (path) => dispatch( push(path) ),
  }
}


let Component = (props) => {

  // when called, this will call goto on props which inturn will dispatch the `push` method.
  let gotoNewPage = () => {
    props.goto('/some/page');
  }

  return (
    <div>
      <h1>Hello World</h1>
      <button onClick={ gotoNewPage }>Goto New Page</button>
    </div>
  );

}

【讨论】:

  • 不过是 react-router-redux
猜你喜欢
  • 2017-09-13
  • 2019-04-22
  • 2018-08-20
  • 2016-05-03
  • 2016-03-26
  • 2017-01-05
  • 2016-06-26
  • 1970-01-01
  • 2020-05-19
相关资源
最近更新 更多