我有一个按钮,按下它时应该切换列表中的更多项目。我在构造函数中设置了默认状态:
constructor(props) {
super(props)
this.state = {
showCount: 10,
expanded: false
}
}
因此,列表中的默认项目数为10,并且未展开。然后我创建了一个应该更改状态并加载更多列表项的函数:
loadMore() {
const { showCount } = this.state
const { events } = this.props
showCount === 10
? this.setState({ showCount: events.reverse().length, expanded: true })
: this.setState({ showCount: 10, expanded: false })
}
创建一个"按钮"如果expanded
状态为真或假,则应该更改它的文本:
const toggleMore = (
<div className="text-center">
<a className="show-more" onClick={() => this.loadMore()}>
{this.state.expanded ? (
<span>Visa mindre</span>
) : (
<span>Visa mer</span>
)}
</a>
</div>
)
然后使用带有.slice
变量的showCount
的列表项组件:
const mappedEvents =
events.length === 0 ? (
<p style={{ textAlign: 'center' }}>No events</p>
) : (
events
.reverse()
.slice(0, this.state.showCount)
.map((event, i) => {
return (
<div>
<EventItem
key={i}
...
/>
</div>
)
})
)
所以这个按钮在我第一次使用时效果很好。如果我来到我的页面,我可以看到所有10个列表项,按下按钮时文本会发生变化。 但当我再次按下它时(expanded: true
)我的所有列表项消失。当我第三次按下它时,我的列表项的顺序发生了变化,这意味着.revers()
显然不再有效了。当我第四次按它时,它会回到第一阶段; 10个列表项和ordning是应该的。之后,它不断重复。
所以我只想知道我在这里做错了什么以及为什么按钮就像这样。
感谢阅读!
答案 0 :(得分:2)
基本问题是events.reverse()是破坏性的,它实际上变异原始数组,它不会简单地返回一个新的反向数组。这个阵列来自道具这也是一个问题 - 你绝对不应该修改来自道具的东西,你不知道父组件是否会在以后用新阵列覆盖它。
此外,如果您在渲染过程中使用reverse(),请记住渲染可能会运行一堆您可能会意识到的更多次。每次渲染它都会再次反转阵列。
我在这里建议的只是在渲染过程中执行数组变换,并以非破坏性方式执行。获得新的反向数组的一种方法是首先使用切片创建一个副本,然后然后将其反转,如下所示:
const reversed = events.slice().reverse();
另外我注意到你正在使用events.reverse().length
- 可能这与events.length相同,你需要在这里改变数组吗?
答案 1 :(得分:0)
我取下了倒车部件,我不确定你到底需要它。并将这些功能分解为单独的方法,甚至是单独的小组件。
以下是代码:
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
render() {
return (
<List events={[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]} />
);
}
}
class List extends Component {
constructor(props) {
super(props)
this.state = {
showCount: 10,
expanded: false
}
this.renderMappedEvents = this.renderMappedEvents.bind(this);
this.renderToggleMoreBtn = this.renderToggleMoreBtn.bind(this);
}
loadMore() {
const { showCount } = this.state
const { events } = this.props
showCount === 10
? this.setState({ showCount: events.length, expanded: true })
: this.setState({ showCount: 10, expanded: false })
}
renderMappedEvents() {
const { events } = this.props;
return events.length === 0 ? (
<p style={{ textAlign: 'center' }}>No events</p>
) : (
events
.slice(0, this.state.showCount)
.map((event, i) => {
return (
<div>
{ event }
</div>
)
})
)
}
renderToggleMoreBtn() {
return (
<div className="text-center">
<a className="show-more" onClick={() => this.loadMore()}>
{this.state.expanded ? (
<span>Visa mindre</span>
) : (
<span>Visa mer</span>
)}
</a>
</div>
);
}
render() {
return (
<div>{[
this.renderMappedEvents(),
this.renderToggleMoreBtn()
]}</div>);
}
}
render(<App />, document.getElementById('root'));
指向工作代码段的链接: https://stackblitz.com/edit/react-kmdz9f