我是React JavaScript的新手。以前,我是使用WPF的桌面应用程序开发人员,并且在我的桌面应用程序中广泛使用Frame
和Page
。我想用React JavaScript达到几乎相同的目的。我想用React JavaScript做一个底部的标签栏。这是我目前的工作:
App.js
:
import './App.css';
import React, { Component } from 'react';
import BottomTabBar from './BottomTabBar/BottomTabBar';
import HomePage from './HomePage/HomePage';
class App extends Component {
render() {
let menuItems = [];
menuItems.push({
label: 'Home',
faIcon: 'fas fa-home',
content: (
<HomePage/>
)
});
menuItems.push({
label: 'Numbers',
faIcon: 'fas fa-ellipsis-h',
content: (
<h1>
This is numbers page.
</h1>
)
});
menuItems.push({
label: 'Notifications',
faIcon: 'fas fa-bell',
content: (
<h1>
This is notifications page.
</h1>
)
});
menuItems.push({
label: 'Menu',
faIcon: 'fas fa-bars',
content: (
<h1>
This is menu page.
</h1>
)
});
return (
<div
className='App'
>
<BottomTabBar
menuItems={menuItems}
/>
</div>
);
}
}
export default App;
BottomTabBar.js
:
import './BottomTabBar.css';
import '../Ripple.css';
import React, { Component } from 'react';
class BottomTabBar extends Component {
constructor() {
super();
this.state = {
content: null,
selectedTabIndex: 0,
};
}
handleClick = (index) => {
// Changing content.
this.setState({
selectedTabIndex: index
});
}
render() {
// Putting them all.
return (
<div
className='BottomTabBar'
>
<div
className='Content'
>
{this.props.menuItems[this.state.selectedTabIndex].content}
</div>
<div
className='IconsBar'
>
{
this.props.menuItems.map((menuItem, i) => {
return (
<div
className="MenuItem Ripple"
key={i}
onClick={()=>this.handleClick(i)}
>
<div
className="Gap"
/>
<div
className="Icon"
>
<div
className={menuItem.faIcon}
/>
</div>
<div
className="Gap"
/>
<div
className="Text"
>
{menuItem.label}
</div>
</div>
)
})
}
</div>
</div>
);
}
}
export default BottomTabBar;
HomePage.js
:
import './HomePage.css';
import React, { Component } from 'react';
class HomePage extends Component {
constructor() {
super();
this.state = {
counter: 0,
};
}
componentDidMount() {
this.counterInterval = setInterval(() => {
this.setState((prevState) => ({
counter: prevState.counter + 1
}));
}, 1000);
}
componentWillUnmount() {
clearInterval(this.counterInterval);
}
render() {
return (
<div
className='HomePage'
>
Home page counter: {this.state.counter}
</div>
);
}
}
export default HomePage;
您可能从上面的代码中知道,我的主页只是一个简单的页面,具有每秒自动递增的计数器:
问题是我的HomePage
不能持久。如果我尝试在选项卡之间进行切换,那么它可以工作,但是主页上的计数器始终重置为0,这意味着仅在选项卡之间进行导航时,才会重新创建我的主页和其他页面。当我在<HomePage/>
第14行创建App.js
时,这对我来说很奇怪。我做错了什么?随时问我是否需要更多详细信息。
也许我想做的更像是这个库:
https://github.com/lishengzxc/react-no-unmount-hide
我不太确定该库的功能,但是我尝试了一下,但是它不起作用(只是抛出一些奇怪的错误)
答案 0 :(得分:1)
这是可以预期的,因为每次导航 Home 标签时都会创建新的HomePage
实例。
lifting the state up就是这种情况。如果计数器状态应保持不变,则应将其移至选项卡导航中不会破坏的组件,即App
:
class App extends Component {
state = { counter: 0 };
incrementCounter = () => setState((state) => ({ counter: state.counter + 1 }));
render() {
let menuItems = [];
menuItems.push({
label: 'Home',
faIcon: 'fas fa-home',
content: (
<HomePage counter={this.state.counter} increment={this.incrementCounter} />
)
});
...
应使用这些道具代替本地HomePage
状态:
this.counterInterval = setInterval(this.props.increment);
和
Home page counter: {this.props.counter}
一种替代方法是使用Redux或React上下文API来管理全局应用程序状态。
答案 1 :(得分:0)
答案 2 :(得分:0)
经过几个小时的努力,我终于根据自己的想法做到了。这是那些好奇的代码:
App.js:
import './App.css';
import React, { Component } from 'react';
import BottomTabBar from './BottomTabBar/BottomTabBar';
import HomePage from './HomePage/HomePage';
import NumbersPage from './NumbersPage/NumbersPage';
class App extends Component {
render() {
let menuItems = [];
menuItems.push({
label: 'Home',
faIcon: 'fas fa-home'
});
menuItems.push({
label: 'Numbers',
faIcon: 'fas fa-ellipsis-h'
});
return (
<div
className='App'
>
<BottomTabBar
menuItems={menuItems}
>
<HomePage/>
<NumbersPage/>
</BottomTabBar>
</div>
);
}
}
export default App;
BottomTabBar.js:
import './BottomTabBar.css';
import '../Ripple.css';
import React, { Component } from 'react';
class BottomTabBar extends Component {
constructor() {
super();
this.state = {
selectedIndex: 0,
};
console.log('Initialized bottom tab bar');
}
handleClick = (index) => {
// Changing content.
this.setState({
selectedIndex: index
});
}
render() {
return (
<div
className='BottomTabBar'
>
<div
className='Content'
>
{
this.props.children.map((child, i) => {
return (
<div
style={{
display: i == this.state.selectedIndex
? 'block'
: 'none'
}}
key={i}
>
{child}
</div>
)
})
}
</div>
<div
className='IconsBar'
>
{
this.props.menuItems.map((menuItem, i) => {
return (
<div
className="MenuItem Ripple"
key={i}
onClick={()=>this.handleClick(i)}
>
<div
className="Gap"
/>
<div
className="Icon"
>
<div
className={menuItem.faIcon}
/>
</div>
<div
className="Gap"
/>
<div
className="Text"
>
{menuItem.label}
</div>
</div>
)
})
}
</div>
</div>
);
}
}
export default BottomTabBar;
HomePage.js:
import './HomePage.css';
import React, { Component } from 'react';
class HomePage extends Component {
constructor() {
super();
this.state = {
counter: 0,
};
console.log('Initialized home page');
}
componentDidMount() {
this.counterInterval = setInterval(() => {
this.setState((prevState) => ({
counter: prevState.counter + 1
}));
}, 1000);
}
componentWillUnmount() {
clearInterval(this.counterInterval);
}
render() {
return (
<div
className='HomePage'
style={this.props.style}
>
Home page counter: {this.state.counter}
</div>
);
}
}
export default HomePage;
注意:NumbersPage.js基本上只是一个带有很长的lorem ipsum文本的页面。
就是这样,所有状态都保留下来而没有解除。不会保留NumbersPage.js上的滚动位置,因为我在那儿使用了css display属性,而那是正常的:)
感谢您的帮助!