Reactjs 重定向上的React导航组件在刷新时丢失数据
我使用的是React 16.4.1和React路由器Dom 4.3.1。我已经使用一个web组件构建了一个侧栏react组件,您可以将数据传递到web组件中,这将呈现该组件Reactjs 重定向上的React导航组件在刷新时丢失数据,reactjs,Reactjs,我使用的是React 16.4.1和React路由器Dom 4.3.1。我已经使用一个web组件构建了一个侧栏react组件,您可以将数据传递到web组件中,这将呈现该组件 import React from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import { Redirect } from 'react-router-dom'; class Sidebar extend
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { Redirect } from 'react-router-dom';
class Sidebar extends React.Component {
constructor(props, context) {
super(props, context);
this.mySideBarRef = React.createRef();
this.menuClick = this.menuClick.bind(this);
this.state = {
redirect: false,
redirectUrl: '/',
menuData: [
{
groupName: 'Group 1',
icon: 'Home',
children: [
{
title: 'Home',
icon: 'favorite',
url: '/',
},
{
title: 'Grp 1 Item 2',
children: [
{
title: 'Roles',
icon: 'Person',
url: '/roles',
},
{
title: 'About',
icon: 'gesture',
url: '/about',
},
{
title: 'Google',
icon: 'world',
url: 'http://www.google.co.uk',
},
],
},
],
},
{
groupName: 'Group 2',
icon: 'search',
children: [
{
title: 'Grp 2 Item 1',
icon: 'microsoft',
children: [
{
title: 'Grp 2 Item 1.1 Bing',
icon: '',
url: 'http://www.google.co.uk',
},
{
title: 'Grp 2 Item 1.2 Bing',
icon: '',
url: 'http://www.bing.com',
},
],
},
],
},
],
};
}
componentDidMount() {
let sideMenuContainer = this.mySideBarRef.current;
sideMenuContainer.sideMenuData = this.state.menuData;
sideMenuContainer.overrideCustomUrlEvent = true;
window.addEventListener('customUrlEvent', this.menuClick)
}
menuClick(e) {
console.log(e);
this.setState({
redirect: true,
redirectUrl: e.url
});
}
componentWillUnmount() {
this.mySideBarRef.current.removeEventListener('customUrlEvent', this.menuClick);
}
render() {
if(this.state.redirect) {
this.state.redirect = false;
return <Redirect to={this.state.redirectUrl} />;
}
if(this.state.menuData !== null) {
return(
<side-bar-component
ref={this.mySideBarRef}
collapsable>
</side-bar-component>
);
}
}
}
export default Sidebar;
这是侧杆组件
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { Redirect } from 'react-router-dom';
class Sidebar extends React.Component {
constructor(props, context) {
super(props, context);
this.mySideBarRef = React.createRef();
this.menuClick = this.menuClick.bind(this);
this.state = {
redirect: false,
redirectUrl: '/',
menuData: [
{
groupName: 'Group 1',
icon: 'Home',
children: [
{
title: 'Home',
icon: 'favorite',
url: '/',
},
{
title: 'Grp 1 Item 2',
children: [
{
title: 'Roles',
icon: 'Person',
url: '/roles',
},
{
title: 'About',
icon: 'gesture',
url: '/about',
},
{
title: 'Google',
icon: 'world',
url: 'http://www.google.co.uk',
},
],
},
],
},
{
groupName: 'Group 2',
icon: 'search',
children: [
{
title: 'Grp 2 Item 1',
icon: 'microsoft',
children: [
{
title: 'Grp 2 Item 1.1 Bing',
icon: '',
url: 'http://www.google.co.uk',
},
{
title: 'Grp 2 Item 1.2 Bing',
icon: '',
url: 'http://www.bing.com',
},
],
},
],
},
],
};
}
componentDidMount() {
let sideMenuContainer = this.mySideBarRef.current;
sideMenuContainer.sideMenuData = this.state.menuData;
sideMenuContainer.overrideCustomUrlEvent = true;
window.addEventListener('customUrlEvent', this.menuClick)
}
menuClick(e) {
console.log(e);
this.setState({
redirect: true,
redirectUrl: e.url
});
}
componentWillUnmount() {
this.mySideBarRef.current.removeEventListener('customUrlEvent', this.menuClick);
}
render() {
if(this.state.redirect) {
this.state.redirect = false;
return <Redirect to={this.state.redirectUrl} />;
}
if(this.state.menuData !== null) {
return(
<side-bar-component
ref={this.mySideBarRef}
collapsable>
</side-bar-component>
);
}
}
}
export default Sidebar;
**
很抱歉我反应迟钝,但我期待你的回答
帮助再次感谢你们的支持
**
还包括my routes.js,以防可能需要它来帮助解决此问题
import React from 'react';
import { Route, IndexRoute, Switch } from 'react-router-dom';
// import { Route, IndexRoute } from 'react-router';
import App from './components/app';
import HomePage from './components/home/home-page';
import AboutPage from './components/about/about-page';
import RolesPage from './components/role/roles-page';
import ManageRolePage from './components/role/manage-role-page'; //eslint-disable-line import/no-named-as-default
export default (
<Switch>
<Route path="/" components={App}>
<IndexRoute component={HomePage} />
<Route path="roles" component={RolesPage}/>
<Route path="role" component={ManageRolePage}/>
<Route path="role/:id" component={ManageRolePage}/>
<Route path="about" component={AboutPage}/>
</Route>
</Switch>
);
这意味着状态没有被更新,但我可以保留菜单展开,但页面不会重定向,因为我没有点击渲染函数事件。组件将在其状态或道具更改时重新渲染,这意味着它们的
渲染
方法将再次运行,以及它们的相关生命周期方法
关于您的代码,我注意到最多的是您正在使用路由
,但您没有使用交换机
或浏览器路由器
。这可能是相关的。我不能确定,但因为您的
组件位于路由的上游,除非其状态或道具发生更改,否则它将不会重新渲染或更新
我认为你的边栏不会更新,数据可能会在最初加载,但会变得陈旧
但不要害怕,请允许我给你链接一篇文章,我认为这篇文章将把你带到下一个层次:(给未来的个人注意:如果这个URL在未来中断,请让我知道)
我想你读了之后会明白的,但它会详细说明浏览器路由器
,交换机
,以及路由
。我认为你需要改变你的代码来使用这三个
请记住,侧边栏(及其所有子项)只有在其状态或道具发生更改时才会更新
你可以这样做:
class App extends Component {
constructor(props) {
super(props)
this.state = {
data: {},
}
}
render() {
return (
<div>
<Sidebar data={this.state.data} />
<AnotherComponent onEventOccurred={newData => this.setState({ data: newData })} />
</div>
)
}
}
该组件有一个名为oneventoccured
的属性,可以从该组件内部调用该属性作为this.props.oneventoccured(newData)
,或者如果功能性非类组件作为props.oneventoccured()
。它实际上只是一个回调,所以你调用它,它在其父级中激发this.setState()
。这是一个非常强大的模式,因为它允许父级控制它将为该事件执行的操作,因为操作是在父级中定义的。子对象只是触发回调
起初我很犹豫是否要发布一个答案,但现在我觉得你可能会从中受益匪浅。如果还不清楚具体情况,请告诉我。我想让你先看看我链接的那篇媒体文章。其中显示的模式非常常见且惯用
我刚注意到你安装了Redux。总的来说,这确实增加了复杂性,但对于跨领域的关注点来说是好的。有时我们称之为横向数据加载。通常,React中的数据是单向流动的,这意味着总是从父级到子级,从上游到下游
使用Redux,您可以从任何组件调用动作创建者,并且边栏将监听状态对象上的更改。当您希望在多个未直接连接的组件之间共享状态片段时,可以使用Redux
使用Redux,连接的组件将侦听“基本”全局状态树上的更改。当状态更改时,订阅的组件将更新
例如,在侧边栏中,可以有以下内容:
function mapStateToProps(state, ownProps) {
return {
loading: state.ajaxCallsInProgress > 0,
data: state.sidebar,
};
}
每次更改state.sidebar
时,它都会更新其this.props.data
。我尽量把这件事保持在最低限度,因为我可能会用额外的信息把你搞糊涂,但这是最重要的部分。使用connect()
的组件订阅全局状态树上的更改
Connect是一个高阶组件,它使用该组件包装组件,因此当应用程序的状态发生变化时,它会导致该组件的道具发生变化,从而触发重新渲染。嗨,Adam,首先感谢您的回复。你的建议很好,谢谢你。我正在尝试你推荐的几种方法,并将反馈我是如何做到这一点的。鲍比,我看到你编辑了我的答案,结果被拒绝了。试着把同样的东西贴到问题的底部。堆栈溢出不是做这种增量插件类型事情的最佳方式。如果您丢失了更改,我仍然可以在被拒绝的评论中看到它们。让我知道,我会更仔细地检查它们,但最好的补充是在你的问题中,比如:“基于以下答案的新内容”。幸运的是,我没有关闭我的机器,因此能够进入浏览器历史记录以获取此信息。:)没有完全解决我的问题,但为我指明了正确的方向。
if(this.state.sideMenu.menuData !== undefined) {
sideMenuContainer.sideMenuData = this.state.sideMenu.menuData;
}
import React from 'react';
import { Route, IndexRoute, Switch } from 'react-router-dom';
// import { Route, IndexRoute } from 'react-router';
import App from './components/app';
import HomePage from './components/home/home-page';
import AboutPage from './components/about/about-page';
import RolesPage from './components/role/roles-page';
import ManageRolePage from './components/role/manage-role-page'; //eslint-disable-line import/no-named-as-default
export default (
<Switch>
<Route path="/" components={App}>
<IndexRoute component={HomePage} />
<Route path="roles" component={RolesPage}/>
<Route path="role" component={ManageRolePage}/>
<Route path="role/:id" component={ManageRolePage}/>
<Route path="about" component={AboutPage}/>
</Route>
</Switch>
);
menuClick(e) {
console.log(e);
this.redirectUrl = e.url;
this.redirect = true;
}
class App extends Component {
constructor(props) {
super(props)
this.state = {
data: {},
}
}
render() {
return (
<div>
<Sidebar data={this.state.data} />
<AnotherComponent onEventOccurred={newData => this.setState({ data: newData })} />
</div>
)
}
}
<AnotherComponent onEventOccurred={newData => this.setState({ data: newData })} />
function mapStateToProps(state, ownProps) {
return {
loading: state.ajaxCallsInProgress > 0,
data: state.sidebar,
};
}