我正在一个社区站点上,用户可以在该站点上共享和评论网站(在这里)[https://beta.getkelvin.com/]。可以按类别过滤网站,但是当用户进入特定页面然后退出时,过滤器将被删除。
这是分步进行的过程:
this.state.topicSelected
反映新值this.state.topicSelected
反映正确的值this.state.topicSelected
恢复为0
我希望值仍然适用,而不是恢复为0,因此过滤器仍与用户之前选择的类别相同。
问题似乎是getInitialState
正在将this.state.topicSelected
的值重新设置为0
(如代码中所写)。尝试将动态值放在0
的位置时,出现未定义的错误。
这是getInitialState
代码:
var SitesArea = React.createClass({
getInitialState: function () {
return {
sortSelected: "most-recent",
topicSelected: 0 // need to overwrite with value of this.state.topicSelected when user selects filter
// I removed other attributes to clean it up for your sake
}
}
这是事件:
onTopicClick: function (e) {
e.preventDefault();
this.setState({topicSelected: Number(e.target.value)});
if (Number(e.target.value) == 0) {
if (this.state.sortSelected == 'highest-score') {
this.setState({sites: []}, function () {
this.setState({sites: this.state.score});
});
} else if (this.state.sortSelected == 'most-remarked') {
this.setState({sites: []}, function () {
this.setState({sites: this.state.remarkable});
});
} else if (this.state.sortSelected == 'most-visited') {
this.setState({sites: []}, function () {
this.setState({sites: this.state.visited});
});
} else if (this.state.sortSelected == 'most-recent') {
this.setState({sites: []}, function () {
this.setState({sites: this.state.recent});
});
}
} else {
this.getSites(this.state.sortSelected, Number(e.target.value));
this.setState({sites: []}, function () {
this.setState({sites: this.state.filter_sites});
});
}
最后是下拉菜单:
<select
value={this.state.topicSelected}
onChange={this.onTopicClick}
className="sort"
data-element>
{
// Add this option in the .then() when populating siteCategories()
[<option key='0'value='0'>Topics</option>].concat(
this.state.topics.map(function (topic) {
return (<option
key={topic.id}
value={topic.id}>{topic.name}</option>);
}))
}
如何获取该信息,以便在用户返回主页时不会重置this.state.topicSelected
?
答案 0 :(得分:1)
我认为当用户从主页导航到摘要页面时,您的主页将被卸载(销毁)。当它们返回时,React为主页组件创建一个全新的实例。重构将所选主题初始化回0。
Here is a codepen显示可能发生的情况。 Foo
==您的主页,Bar
==摘要页面。单击几次递增主题,然后从Foo
导航到Bar
,然后再次返回。控制台日志显示,Foo
组件在您离开时会被卸载,并在返回时进行重构。
注意,您似乎正在使用旧版本的react,如getInitialState
和React.createClass
的存在所证明。我的笔遵循了在类构造函数中初始化状态的更现代方法。
要解决此问题,您必须将该状态保存在主要组件之外的某些内容中,这些内容在导航时不会被删除或重新创建。这是一些这样做的选择
onTopicSelected
事件。主页的父级将传入函数处理程序,作为挂钩该事件的道具。处理程序应将所选主题保存在父级的组件状态中。这是一种混乱的解决方案,因为父母通常不应该了解或关心子女的内部状态window.props
。这也是一个丑陋的主意。Redux是存储此状态的最干净的方法,但这需要一些学习。如果您想看看它的外观,我已经在this codepen中实现了第一个解决方案。
显示该问题的原始Codepen作为摘要粘贴在下面。如果尝试在此处运行,请切换到整页模式。
//jshint esnext:true
const Header = (props) => {
const {selectedPage, onNavigationChange} = props;
const disableFoo = selectedPage == 'foo'
const disableBar = selectedPage == 'bar';
return (
<div>
<h1>Header Component : {selectedPage}</h1>
<button disabled={disableFoo} onClick={() => onNavigationChange('foo')}>Foo page</button>
<button disabled={disableBar} onClick={() => onNavigationChange('bar')}>Bar page</button>
<hr/>
</div>
);
};
class Foo extends React.Component {
constructor(props) {
console.log('Foo constructor');
super(props);
this.state = {
topicSelected: 0
};
this.incrementTopic = this.incrementTopic.bind(this);
}
incrementTopic() {
const {topicSelected} = this.state
const newTopic = topicSelected + 1
console.log(`incrementing topic: old=${topicSelected} new=${newTopic}`)
this.setState({
topicSelected: newTopic
})
}
render() {
console.log('Foo::render');
return (<div>
<h2>The Foo content page : topicSelected={this.state.topicSelected}</h2>
<button onClick={this.incrementTopic}>Increment topic</button>
</div>
);
}
componentWillMount() {
console.log('Foo::componentWillMount');
}
componentDidMount() {
console.log('Foo::componentDidMount');
}
componentWillUnmount() {
console.log('Foo::componentWillUnmount');
}
componentWillUpdate() {
console.log('Foo::componentWillUpdate');
}
componentDidUpdate() {
console.log('Foo::componentDidUpdate');
}
}
const Bar = (props) => {
console.log('Bar::render');
return <h2>The Bar content page</h2>
}
const Body = (props) => {
console.log('Body::render');
const {selectedPage} = props;
if (selectedPage == 'foo') {
return <Foo/>;
} else if (selectedPage == 'bar') {
return <Bar/>
}
};
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedPage: 'foo'
};
}
render() {
console.log('Application::render');
const {selectedPage} = this.state;
const navigationChange = (nextPage) => {
this.setState({
selectedPage: nextPage
})
}
return (
<div>
<Header selectedPage={selectedPage} onNavigationChange={navigationChange}/>
<Body selectedPage={selectedPage}/>
</div>
);
}
}
ReactDOM.render(<Application/>,
document.getElementById('main')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="main"></div>