React-router 组件不会在 <Link> 导航上更新
React-router component does not update on <Link> navigation
由于许多其他人遇到了同样的问题,我正在努力与 <Link> element to change routes and render a new component. I am able to click on the link and the path for my application changes in my redux store, but no component gets updated. My root component does not seem to respond to shouldComponentUpdate, even though props are changing and the full setup is similar to how connected-react-router 描述的互动。
待测
示例代码(git 回购)是一个 MVP(最小可行产品)——它可以很容易地复制我遇到的问题。
git clone https://github.com/reZach/electron-webpack-template.git
cd electron-webpack-template
npm i
npm run dev
如果您更喜欢查看文件,我在下面包含了必要的文件
index.js
import React from "react";
import ReactDOM from "react-dom";
import Root from "../app/components/core/root";
import store, { history } from "./redux/store/store";
ReactDOM.render(
<Root store={store} history={history}></Root>,
document.getElementById("root")
);
store.js
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { createBrowserHistory } from "history";
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createBrowserHistory();
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;
root.jsx
import React from "react";
import { ConnectedRouter } from "connected-react-router";
import { Provider, connect } from "react-redux";
import Routes from "../core/routes";
class Root extends React.Component {
render() {
return (
<Provider store={this.props.store}>
<ConnectedRouter history={this.props.history}>
<Routes></Routes>
</ConnectedRouter>
</Provider>
);
}
}
export default Root;
routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
routes.json
{
"ENTRY": "/",
"MAIN": "/main"
}
package.json
{
"name": "electron-webpack-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "npm run build-dev-webpack && npm run start-dev-app",
"build-dev-webpack": "webpack --mode development --config ./app/configs/webpack/webpack.config.js",
"start-dev-app": "cross-env NODE_ENV=development electron app/main.js",
"prod": "npm run build-prod-webpack && npm run start-prod-app",
"build-prod-webpack": "webpack --mode production --config ./app/configs/webpack/webpack.config.js",
"start-prod-app": "cross-env NODE_ENV=production electron app/main.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/reZach/electron-webpack-template.git"
},
"keywords": [],
"author": "",
"license": "GPL-3.0-only",
"bugs": {
"url": "https://github.com/reZach/electron-webpack-template/issues"
},
"homepage": "https://github.com/reZach/electron-webpack-template#readme",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-proposal-json-strings": "^7.7.4",
"@babel/plugin-transform-react-jsx": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"babel-loader": "^8.0.6",
"cross-env": "^6.0.3",
"csp-html-webpack-plugin": "^3.0.4",
"devtron": "^1.4.0",
"electron": "^7.1.7",
"html-webpack-plugin": "^3.2.0",
"lockfile-lint": "^3.0.5",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
},
"dependencies": {
"@reduxjs/toolkit": "^1.2.1",
"connected-react-router": "^6.6.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"redux": "^4.0.5"
}
}
这可能是因为 Entry 路由(对于 App 组件)没有 "exact" 词:
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
解决这些路由问题的方法是按照 drazewski 的建议添加 exact
属性,另外更改我用于 [=13] 的历史记录对象=].问题是由于我使用 createBrowserHistory 以及我 而不是 在我的应用程序中使用网络服务器来托管我的文件这一事实造成的。加载我的应用程序时,我的应用程序的默认路径是 file:///C:/...index.html
。这是我在加载应用程序时查看我的 Redux 商店时的路径值。
我不得不改为使用 createHashHistory,当您没有托管网络服务器来托管您的应用程序时,它会起作用。使用 createHashHistory 时的默认路径是 /
,它与我的 routes.jsx 文件中的 routes.ENTRY
匹配,并允许我导航到 /main
。显然,除非您的路径与您在 <Route>
中定义的现有路径相匹配,否则您无法导航到另一条路径(这就是我 认为 发生的事情,因为我描述了我的上面的问题 - 虽然我不知道为什么我的 home/page1 组件会呈现......)。
这里
是很好的参考资料,指出了我必须改变历史的方向 (here and here). In addition to those links, here is a good blog post (mirror) explaining more in-detail the various types of history for react-router.
新routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route> <!-- updated -->
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
新store.js
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { createHashHistory } from "history"; // < updated!
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createHashHistory(); // < updated!
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;
由于许多其他人遇到了同样的问题,我正在努力与 <Link> element to change routes and render a new component. I am able to click on the link and the path for my application changes in my redux store, but no component gets updated. My root component does not seem to respond to shouldComponentUpdate, even though props are changing and the full setup is similar to how connected-react-router 描述的互动。
待测
示例代码(git 回购)是一个 MVP(最小可行产品)——它可以很容易地复制我遇到的问题。
git clone https://github.com/reZach/electron-webpack-template.git
cd electron-webpack-template
npm i
npm run dev
如果您更喜欢查看文件,我在下面包含了必要的文件
index.js
import React from "react";
import ReactDOM from "react-dom";
import Root from "../app/components/core/root";
import store, { history } from "./redux/store/store";
ReactDOM.render(
<Root store={store} history={history}></Root>,
document.getElementById("root")
);
store.js
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { createBrowserHistory } from "history";
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createBrowserHistory();
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;
root.jsx
import React from "react";
import { ConnectedRouter } from "connected-react-router";
import { Provider, connect } from "react-redux";
import Routes from "../core/routes";
class Root extends React.Component {
render() {
return (
<Provider store={this.props.store}>
<ConnectedRouter history={this.props.history}>
<Routes></Routes>
</ConnectedRouter>
</Provider>
);
}
}
export default Root;
routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
routes.json
{
"ENTRY": "/",
"MAIN": "/main"
}
package.json
{
"name": "electron-webpack-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "npm run build-dev-webpack && npm run start-dev-app",
"build-dev-webpack": "webpack --mode development --config ./app/configs/webpack/webpack.config.js",
"start-dev-app": "cross-env NODE_ENV=development electron app/main.js",
"prod": "npm run build-prod-webpack && npm run start-prod-app",
"build-prod-webpack": "webpack --mode production --config ./app/configs/webpack/webpack.config.js",
"start-prod-app": "cross-env NODE_ENV=production electron app/main.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/reZach/electron-webpack-template.git"
},
"keywords": [],
"author": "",
"license": "GPL-3.0-only",
"bugs": {
"url": "https://github.com/reZach/electron-webpack-template/issues"
},
"homepage": "https://github.com/reZach/electron-webpack-template#readme",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-proposal-json-strings": "^7.7.4",
"@babel/plugin-transform-react-jsx": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"babel-loader": "^8.0.6",
"cross-env": "^6.0.3",
"csp-html-webpack-plugin": "^3.0.4",
"devtron": "^1.4.0",
"electron": "^7.1.7",
"html-webpack-plugin": "^3.2.0",
"lockfile-lint": "^3.0.5",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
},
"dependencies": {
"@reduxjs/toolkit": "^1.2.1",
"connected-react-router": "^6.6.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"redux": "^4.0.5"
}
}
这可能是因为 Entry 路由(对于 App 组件)没有 "exact" 词:
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
解决这些路由问题的方法是按照 drazewski 的建议添加 exact
属性,另外更改我用于 [=13] 的历史记录对象=].问题是由于我使用 createBrowserHistory 以及我 而不是 在我的应用程序中使用网络服务器来托管我的文件这一事实造成的。加载我的应用程序时,我的应用程序的默认路径是 file:///C:/...index.html
。这是我在加载应用程序时查看我的 Redux 商店时的路径值。
我不得不改为使用 createHashHistory,当您没有托管网络服务器来托管您的应用程序时,它会起作用。使用 createHashHistory 时的默认路径是 /
,它与我的 routes.jsx 文件中的 routes.ENTRY
匹配,并允许我导航到 /main
。显然,除非您的路径与您在 <Route>
中定义的现有路径相匹配,否则您无法导航到另一条路径(这就是我 认为 发生的事情,因为我描述了我的上面的问题 - 虽然我不知道为什么我的 home/page1 组件会呈现......)。
这里 是很好的参考资料,指出了我必须改变历史的方向 (here and here). In addition to those links, here is a good blog post (mirror) explaining more in-detail the various types of history for react-router.
新routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route> <!-- updated -->
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
新store.js
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { createHashHistory } from "history"; // < updated!
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createHashHistory(); // < updated!
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;