react-router-redux webpack dev server historyApiFallback 失败
react-router-redux webpack dev server historyApiFallback fails
在webpack配置文件中启用historyApiFallback并重启服务器后,当更改位置路径名时,浏览器刷新,导致外部元素重新挂载(我的意思是,我可以看到它闪烁白色并返回到normal) 这应该只发生在嵌套的 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"
}
}
};
主要wrapper/container:
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')
);
所以现在我需要能够像在入口点那样从操作中发送推送。这有点令人困惑,因为我将中间件传递给商店,然后商店与浏览器历史记录同步,我想我需要在这两种情况下从 applyMiddleware(routerMiddleware(browserHistory)) 传递 return 值(createstore 和 sunchistorywithstore)?
由于您正在使用 react-router
并且不希望每次切换到新 url 时浏览器都重新加载整个页面,因此使用 <Link>
组件由 react-router
提供或创建您自己的组件版本。
要link不同页面之间可以
import { Link } from 'react-router';
然后在 render
函数中使用它,就像
<Link to="/user/profile">Goto Profile Page</Link>
<Link to="/">Homepage</Link>
如果您想以编程方式将用户重定向到不同的url/location
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>
);
}
在webpack配置文件中启用historyApiFallback并重启服务器后,当更改位置路径名时,浏览器刷新,导致外部元素重新挂载(我的意思是,我可以看到它闪烁白色并返回到normal) 这应该只发生在嵌套的 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"
}
}
};
主要wrapper/container:
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')
);
所以现在我需要能够像在入口点那样从操作中发送推送。这有点令人困惑,因为我将中间件传递给商店,然后商店与浏览器历史记录同步,我想我需要在这两种情况下从 applyMiddleware(routerMiddleware(browserHistory)) 传递 return 值(createstore 和 sunchistorywithstore)?
由于您正在使用 react-router
并且不希望每次切换到新 url 时浏览器都重新加载整个页面,因此使用 <Link>
组件由 react-router
提供或创建您自己的组件版本。
要link不同页面之间可以
import { Link } from 'react-router';
然后在 render
函数中使用它,就像
<Link to="/user/profile">Goto Profile Page</Link>
<Link to="/">Homepage</Link>
如果您想以编程方式将用户重定向到不同的url/location
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>
);
}