为什么我的 useEffect 在修改它的依赖项时没有进入无限循环?
Why doesn't my useEffect go into an infinite loop when modifying it's dependency?
代码
PrizeHistory.js
...
const PrizeHistory = () => {
const [history, setHistory] = useState([]);
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [history])
return (
<View style={styles.body}>
<Text style={styles.text}>Prize History</Text>
</View>
);
}
getAllPrizes
getAllPrizes(db, tableName) {
return new Promise((resolve, reject) => {
db.transaction((tx) => {
tx.executeSql(
`SELECT * FROM ${tableName};`,
[],
(tx, res) => {
let len = res.rows.length;
let results = [];
if(len > 0) {
for(i = 0; i < res.rows.length; i++) {
results.push(res.rows.item(i));
}
}
console.log("resolving promise now");
resolve(JSON.stringify(results));
},
(error) => {
reject(Error(`SQLite getAllPrizes: failed to get '*' from ${tableName}: ` + error));
}
);
});
});
}
目标
页面挂载时,将历史状态设置为数据库中的数据。我最初试过这个:
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [])
但它从未正确设置我的历史变量。我刚得到一个空数组(这是我最初将历史状态设置为的数组)。我希望 history 变量等于 history console.log()
中的结果变量,但事实并非如此。
所以我将 useEffect()
更改为:
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [history])
此代码正确更改了历史变量,但我预计它会进入无限循环...但它没有?这是我的逻辑
useEffect()
有 [history]
作为依赖项
- onMount,
history
设置为默认值[]
useEffect()
看到 history
已设置并开始 运行
useEffect()
重置 history
useEffect()
应该 重新开始,因为它重置了 history
变量本身
- 无限次重复 3-5...
但它不会无限重复...
我的问题
- 为什么当
[history]
被设置为它的依赖时 useEffect()
不是无限地 运行
- 为什么
useEffect()
没有在安装时正确设置我的历史变量,因为它具有 []
作为依赖项。
您第一个问题的答案是:history
在第一次设置后不会改变,因为您的 getAllPrizes
returns 始终是相同的值,因此仅触发 useEffect
一次(在山上)。
对于第 2 个问题,问题是您试图在调用异步的 setHistory
后立即记录 history
值。如果您想在每次更新时记录 history
,您必须执行以下操作:
useEffect(() => {
console.log(history)
}, [history])
您确定您没有尝试在此行设置字符串类型吗:
result == null ? console.log("res is null") : setHistory(result);
据我所知,初始类型是一个数组,解析函数 returns 是一个字符串化对象。
您在控制台中收到任何警告吗?
代码
PrizeHistory.js
...
const PrizeHistory = () => {
const [history, setHistory] = useState([]);
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [history])
return (
<View style={styles.body}>
<Text style={styles.text}>Prize History</Text>
</View>
);
}
getAllPrizes
getAllPrizes(db, tableName) {
return new Promise((resolve, reject) => {
db.transaction((tx) => {
tx.executeSql(
`SELECT * FROM ${tableName};`,
[],
(tx, res) => {
let len = res.rows.length;
let results = [];
if(len > 0) {
for(i = 0; i < res.rows.length; i++) {
results.push(res.rows.item(i));
}
}
console.log("resolving promise now");
resolve(JSON.stringify(results));
},
(error) => {
reject(Error(`SQLite getAllPrizes: failed to get '*' from ${tableName}: ` + error));
}
);
});
});
}
目标
页面挂载时,将历史状态设置为数据库中的数据。我最初试过这个:
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [])
但它从未正确设置我的历史变量。我刚得到一个空数组(这是我最初将历史状态设置为的数组)。我希望 history 变量等于 history console.log()
中的结果变量,但事实并非如此。
所以我将 useEffect()
更改为:
useEffect(() => {
async function getHistory () {
try {
let result = await sqliteInterface.getAllPrizes(db, prizeTable);
result == null ? console.log("res is null") : setHistory(result);
console.log("result" + result);
console.log("history" + history);
} catch (err) {
console.log(err);
}
}
getHistory();
}, [history])
此代码正确更改了历史变量,但我预计它会进入无限循环...但它没有?这是我的逻辑
useEffect()
有[history]
作为依赖项- onMount,
history
设置为默认值[]
useEffect()
看到history
已设置并开始 运行useEffect()
重置history
useEffect()
应该 重新开始,因为它重置了history
变量本身- 无限次重复 3-5...
但它不会无限重复...
我的问题
- 为什么当
[history]
被设置为它的依赖时useEffect()
不是无限地 运行 - 为什么
useEffect()
没有在安装时正确设置我的历史变量,因为它具有[]
作为依赖项。
您第一个问题的答案是:history
在第一次设置后不会改变,因为您的 getAllPrizes
returns 始终是相同的值,因此仅触发 useEffect
一次(在山上)。
对于第 2 个问题,问题是您试图在调用异步的 setHistory
后立即记录 history
值。如果您想在每次更新时记录 history
,您必须执行以下操作:
useEffect(() => {
console.log(history)
}, [history])
您确定您没有尝试在此行设置字符串类型吗:
result == null ? console.log("res is null") : setHistory(result);
据我所知,初始类型是一个数组,解析函数 returns 是一个字符串化对象。 您在控制台中收到任何警告吗?