Javascript 更改组件顺序不会触发重新渲染

Javascript 更改组件顺序不会触发重新渲染,javascript,reactjs,heroku,ecmascript-6,Javascript,Reactjs,Heroku,Ecmascript 6,我正在设计一个系统,显示我的Heroku应用程序何时更新。我遇到的问题是父组件(Herokus)决定了顺序,但我希望它们根据从最新组件开始更新的时间进行排序。通过将日期从Heroku组件传递回父Herokus组件,我能够实现这一点。我尝试添加一个console.log(this.state.apps),它显示排序的顺序,但渲染的组件没有反映出来。我的猜测是,react并没有将组件顺序的改变视为更新视图的理由,但老实说,我没有任何线索。感谢您的帮助。文件如下。对不起,我的代码乱七八糟,为了解决这个

我正在设计一个系统,显示我的Heroku应用程序何时更新。我遇到的问题是父组件(
Herokus
)决定了顺序,但我希望它们根据从最新组件开始更新的时间进行排序。通过将日期从
Heroku
组件传递回父
Herokus
组件,我能够实现这一点。我尝试添加一个
console.log(this.state.apps)
,它显示排序的顺序,但渲染的组件没有反映出来。我的猜测是,react并没有将组件顺序的改变视为更新视图的理由,但老实说,我没有任何线索。感谢您的帮助。文件如下。对不起,我的代码乱七八糟,为了解决这个问题,我重写了三次

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>
    );
  }
}
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;
  }
}
从“React”导入React;
从“./Heroku”导入Heroku;
导出默认类Herokus扩展React.Component{
建造师(道具){
超级(道具);
变量应用=[
“heroku应用程序示例”
]
此.state={
apps:apps.map((h)=>{
返回{
app:h,
更新日期:新日期()
};
})
}
}
sortApps(){
var sorted=this.state.apps.sort((a,b)=>{
返回a.updatedAtx.app==data.app).updatedAt=data.updatedAt;
这是我的国家({
应用程序:应用程序
});
这是sortaps();
这个.forceUpdate();
}
render(){
var s=此;
返回(
{s.state.apps.map((app,i)=>{
返回(
);
})}
);
}
}
Heroku组件:

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>
    );
  }
}
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;
  }
}
从“React”导入React;
导出默认类Ping扩展React.Component{
建造师(道具){
超级(道具);
此.state={
app:props.app,
更新日期:新日期()
};
}
componentDidMount(){
var s=此;
get(`/api/heroku/app/${s.props.app}`{
超时:20000,
})
。然后(res=>{
var数据=资源数据;
s、 设定状态({
app:data.app.name,
更新日期:新日期(data.app['updated_at']))
});
s、 道具更新电流(s.state);
设置间隔(()=>{
var updatedAt=新日期(s.state.updatedAt);
s、 设定状态({
updatedAt:updatedAt
});
}, 1000);
});
}
霍隆加戈(日期){
var ms=新日期()-日期;
var秒=毫秒/1000;
var n=秒;
var后缀=“”;
//不到1分钟
如果(秒<60){
n=秒;
后缀='第二'+(n>1.5?'s':'';
}
//不到1小时
否则如果(秒<3600){
n=秒/60
后缀='minute'+(n>1.5?'s':'';
}
//少于1天
否则如果(秒<86400){
n=秒/3600;
后缀='hour'+(n>1.5?'s':'');
}
//少于1周
否则如果(秒<604800){
n=秒/86400;
后缀='day'+(n>1.5?'s':'';
}
//超过一周
否则{
n=秒/604800;
后缀='周'+(n>1.5?'s':'';
}
返回`${Math.round(n)}${suffix}ago`;
}
render(){
var s=该状态;
var self=这个;
var输出;
//紧凑视图
if(this.props.compact){
输出=(
{s.app}
{self.howLongAgo(s.updatedAt)}

) //全尺寸视图 }否则{ 输出=() } 返回输出; } }
问题似乎在于顺序发生了变化,但由于键基于
i
索引变量,因此记录的列表仍具有相同顺序的相同键。因此,React没有看到任何区别

例如:

未排序的应用程序a、b和c

<div key="1"> //app b
<div key="2"> //app a
<div key="3"> //app c

@西德尼:老实说,你的回答使我走上了正确的道路。谢谢你的帮助。我遇到了一个类似的问题,但是当只有商店的排序顺序改变时,组件的重复器没有改变,添加一个键解决了这个问题,谢谢。