我正在设计一个系统来显示我的 Heroku 应用程序何时更新。我遇到的问题是父组件 (Herokus
) 决定了顺序,但我希望它们根据更新时间从最近的开始进行排序。我能够通过将日期从 Heroku
组件传递回父 Herokus
组件来实现这一点。我尝试添加一个显示排序顺序的 console.log(this.state.apps)
,但这并没有被呈现的组件反射(reflect)出来。我的猜测是 React 没有将更改的组件顺序视为更新 View 的原因 - 但老实说我不知道。任何帮助表示赞赏。文件如下。抱歉,我的代码很乱,我重写了三遍试图解决这个问题。
Herokus 组件:
import React from 'react';
import Heroku from './Heroku';
export default class Herokus extends React.Component {
constructor(props) {
super(props);
var apps = [
'example-heroku-app'
]
this.state = {
apps: apps.map((h) => {
return {
app: h,
updatedAt: new Date()
};
})
}
}
sortApps() {
var sorted = this.state.apps.sort((a, b) => {
return a.updatedAt < b.updatedAt;
});
this.setState({
apps: sorted
});
}
updateParrent(data){
var apps = this.state.apps;
apps.find(x => x.app === data.app).updatedAt = data.updatedAt;
this.setState({
apps: apps
});
this.sortApps();
this.forceUpdate();
}
render() {
var s = this;
return (
<div>
{s.state.apps.map((app, i) => {
return (
<Heroku app={app.app} compact key={`heroku-${i}`} updateParrent={s.updateParrent.bind(s)}/>
);
})}
</div>
);
}
}
Heroku 组件:
import React from 'react';
export default class Ping extends React.Component {
constructor(props) {
super(props);
this.state = {
app: props.app,
updatedAt: new Date()
};
}
componentDidMount() {
var s = this;
axios.get(`/api/heroku/app/${s.props.app}`, {
timeout: 20000,
})
.then(res => {
var data = res.data;
s.setState({
app: data.app.name,
updatedAt: new Date(data.app['updated_at'])
});
s.props.updateParrent(s.state);
setInterval(() => {
var updatedAt = new Date(s.state.updatedAt);
s.setState({
updatedAt: updatedAt
});
}, 1000);
});
}
howLongAgo(date) {
var ms = new Date() - date;
var seconds = ms / 1000;
var n = seconds;
var suffix = '';
// less than 1 minute
if(seconds < 60){
n = seconds;
suffix = 'second' + (n > 1.5 ? 's' : '');
}
// less than 1 hour
else if(seconds < 3600) {
n = seconds / 60
suffix = 'minute' + (n > 1.5 ? 's' : '');
}
// less than 1 day
else if(seconds < 86400) {
n = seconds / 3600;
suffix = 'hour' + (n > 1.5 ? 's' : '');
}
// less than 1 week
else if(seconds < 604800) {
n = seconds / 86400;
suffix = 'day' + (n > 1.5 ? 's' : '');
}
// more than 1 week
else {
n = seconds / 604800;
suffix = 'week' + (n > 1.5 ? 's' : '');
}
return `${Math.round(n)} ${suffix} ago`;
}
render() {
var s = this.state;
var self = this;
var output;
// COMPACT VIEW
if(this.props.compact){
output = (
<div className={'heroku heroku-compact'}>
<h3>{s.app}</h3>
<p>{self.howLongAgo(s.updatedAt)}</p>
<div className='clearfix'></div>
</div>
)
// FULL SIZE VIEW
} else{
output = ()
}
return output;
}
}
最佳答案
问题似乎是顺序发生了变化,但由于键是基于 i
索引变量的,因此记录的列表仍然具有相同顺序的相同键。因此 React 看不出有什么不同。
例子:
未排序的应用程序 a、b 和 c
<div key="1"> //app b
<div key="2"> //app a
<div key="3"> //app c
已排序的应用
<div key="1"> //app a
<div key="2"> //app b
<div key="3"> //app c
应用程序现在的顺序是正确的,但父组件 Herokus 仍然以相同的顺序使用键 1、2 和 3 来显示它们。
解决方法:
将 key 更改为各个 Heroku 组件独有的内容,但与 updatedAt
不同的是将保持不变。在这种情况下,最合乎逻辑的选择是应用名称。
这可以在 Herokus 组件的渲染函数中实现,如下所示:
export default class Herokus extends React.Component {
render() {
var s = this;
return (
<div>
{s.state.apps.map((app, i) => {
return (
<Heroku app={app.app} compact key={`heroku-${app.app}`} updateParrent={s.updateParrent.bind(s)}/>
);
})}
</div>
);
}
}
关于javascript - React 更改组件顺序不会触发重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46959080/