我正在寻找警报,如果 JSON 中发生变化,那么它会更新状态并提醒数据已更改,不幸的是,此步骤循环说"数据已更改",尽管 JSON 数据没有更改。
这是我的代码示例
import React, { Component } from 'react'
class Api extends Component {
constructor(props) {
super(props)
this.state = {
Old_item: []
}
}
GetCryptoData (){
const dataURL = "https://api.coinmarketcap.com/v1/ticker/bitcoin/";
fetch(dataURL)
.then(d => d.json())
.then(d => {
if (this.state.Old_item !== d[0]) {
this.setState({ Old_item: d[0] })
console.log("data changed");
}
})
}
componentDidMount(nextState) {
this.GetCryptoData();
setInterval(this.GetCryptoData.bind(this), 10000);
};
render() {
return (
<div>
{this.state.Old_item.price_usd}
</div>
)
}
}
export default Api
我刚刚编写了一个函数,只要两个对象的结构相同,就可以比较两个对象值。
虽然它没有完全优化,但它可以为您完成这项工作。
function compareObject(obj1, obj2) {
const keys = Object.keys(obj1);
const result = [];
keys.forEach(key => {
if (obj1[key] === obj2[key]) {
result.push(1);
} else {
result.push(0);
}
});
if (result.indexOf(0) === -1) {
return true;
}
return -1;
}
const a ={
"id": "bitcoin",
"name": "Bitcoin",
"symbol": "BTC",
"rank": "1",
"price_usd": "10326.8374041",
"price_btc": "1.0",
"24h_volume_usd": "24838329700.1",
"market_cap_usd": "184082454924",
"available_supply": "17825637.0",
"total_supply": "17825637.0",
"max_supply": "21000000.0",
"percent_change_1h": "-0.46",
"percent_change_24h": "6.27",
"percent_change_7d": "-11.22",
"last_updated": "1563537331"
};
const b = {
"id": "bitcoin",
"name": "Bitcoin",
"symbol": "BTC",
"rank": "1",
"price_usd": "10326.8374041",
"price_btc": "1.0",
"24h_volume_usd": "24838329700.1",
"market_cap_usd": "184082454924",
"available_supply": "17825637.0",
"total_supply": "17825637.0",
"max_supply": "21000000.0",
"percent_change_1h": "-0.46",
"percent_change_24h": "6.27",
"percent_change_7d": "-11.22",
"last_updated": "1563537331"
};
alert(compareObject(a, b));
GetCryptoData (){
const dataURL = "https://api.coinmarketcap.com/v1/ticker/bitcoin/";
fetch(dataURL)
.then(d => d.json())
.then(d => {
if (compareObject(this.state.Old_item[0], d[0]) {
this.setState({ Old_item: d[0] });
}
})
}
这是因为您正在尝试比较两个对象。请参阅下面的代码。
let a = {'a':1};
let b = {'a':1};
if(a!==b){
alert('Not Same!');
}else{
alert('Same!');
}
你认为它们是一样的吗?是的,它们是给我们的,但对于 JavaScript 来说,它们不是,因为当你比较它们时,它们的引用是不相同的,JavaScript 所做的就是比较它们的引用。
因此,最好可以根据 JSON 中的某些属性进行比较或检查。
您需要对当前代码进行少量更改
- 你以错误的方式进行比较。这不是比较对象数组的正确方法。您需要比较键以检查值是否更改
- setState 是异步的,因此控制台.log在状态为设置。所以,这就是为什么控制台应该在setState的回调中。
您的新代码如下所示
class Api extends Component {
constructor(props) {
super(props)
this.state = {
Old_item: []
}
}
GetCryptoData (){
const dataURL = "https://api.coinmarketcap.com/v1/ticker/bitcoin/";
fetch(dataURL)
.then(d => d.json())
.then(d => {
if (this.state.Old_item["INDEX"]["YOUR KEY"] !== d["INDEX]["YOUR KEY"]) {
this.setState({ Old_item: d[0] },()=>{
console.log("data changed");
})
}
})
}
componentDidMount(nextState) {
this.GetCryptoData();
setInterval(this.GetCryptoData.bind(this), 10000);
};
render() {
return (
<div>
{this.state.Old_item.price_usd}
</div>
)
}}
export default Api
就像上面提到的每个人一样,你不能比较这样的对象。因为对象不是基元文字。这意味着它们是通过引用而不是通过值传递的。简单来说
let obj1 = { a: 1 };
let obj2 = { a : 1 };
obj1 !== obj2;
所以我通常使用自己的不同函数来比较对象。如果您只需要进行浅层比较,那么以下简单函数就足够了。如果你需要的不仅仅是一个浅层的比较,那么你需要一个更复杂的函数。
const areObjectsEqual = (obj1 = {}, obj2 = {}) => Object
.keys(obj1).length === Object.keys(obj2).length
&& Object.keys(obj1).every(key => obj1[key] === obj2[key]);
而不是使用:
if (this.state.Old_item !== d[0](
只是做
if (!areObjectsEqual(this.state.Old_item, d[0](
如果问题仍然存在,则可能是由于对象深度嵌套或状态的异步性质。因此,您必须查看这些因素。