为什么 React-app 状态不是 re-rendering 这里?如何让状态及时更新
Why is React-app state not re-rendering here? How to get state to update in time
我想弄清楚这是如何工作的。
我有一个 'pageCounter' 变量用于跟踪当前页面(在 prev/next 按钮单击时更新),当它更新时,我想将选项卡的标题更改为新页面数据.
当我单击下一步按钮时,它不会呈现,除非我单击它两次并且控制台日志显示它尚未更新。但是当我点击下一步后点击我的 'log' 按钮时,它说它已经更新了?
我进行了研究并假设这是由于 'setState' 函数的异步性质造成的。但是,我不确定如何解决这个问题?
我尝试将 updateTitles 函数放入 useEffect
钩子中,但无论是将函数的内容复制到其中,还是调用钩子中的函数,都会出现错误。
我错过了什么?
将 updateTitles
的内容放入 useEffect
时出现的错误是:
Maximum Update Depth Exceeded.
组件代码如下:(code sandbox here)
import React from "react";
import "./styles.css";
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Blah1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "MrMagoo",
Option2: "Nins",
Option3: "Pottao"
};
function updateTitles() {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}
function nextPage() {
if (pageCounter < 3) {
setPage(pageCounter + 1);
updateTitles();
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1);
updateTitles();
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={prevPage} id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{}</p>
<button onClick={nextPage} id="next">
Next
</button>
<button onClick={printLog} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
这是我尝试改用钩子 useEffect 时的代码,但我收到一条错误消息 "Maximum Update Depth Exceeded"。
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "Page 1.11",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "Page 1.1",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Page 2.1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "Page 3.1",
Option2: "Nins",
Option3: "Pottao"
};
useEffect(() => {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}, [pageCounter, pageOneTitles, pageTwoTitles, pageThreeTitles]);
function nextPage() {
if (pageCounter < 3) {
setPage(pageCounter + 1);
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1);
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={prevPage} id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{pageCounter}</p>
<button onClick={nextPage} id="next">
Next
</button>
<button onClick={printLog} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
这是 useEffect 挂钩的代码沙箱:https://codesandbox.io/s/thirsty-panini-mkdzh
我认为这应该可行:
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Blah1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "MrMagoo",
Option2: "Nins",
Option3: "Pottao"
};
function updateTitles() {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}
function nextPage() {
if (pageCounter < 3) {
setPage(prev => prev + 1, updateTitles());
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1, updateTitles());
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={() => prevPage() } } id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{}</p>
<button onClick={() => { nextPage() }} id="next">
Next
</button>
<button onClick={() => { printLog() }} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
onClick
应该传递一个回调来调用函数而不是调用它。
此外,我没有看到您在代码段
中使用 useEffect
每次状态更新 useEffect
运行s。确保将其设置为
useEffect(()=> {
// do stuff with pagecounter , which is updated count
},[pageCount])
如果你想运行它只安装一次
useEffect(()=> {
// do stuff with pagecounter , which is initial count
},[])
useEffect 也在第一次渲染时 运行s,避免 运行在初始渲染时使用
const [pageCount, setPageCount] = useState(0)
useEffect(()=> {
if (pageCount===0){
//this prevent to run on first render
return
}
// code here will only run on updating state
},[pageCount])
结合useEffect()
和useCallback()
函数。
useEffect(()=> {
updateTitles();
},[pageCounter]);
const updateTitles = useCallback(() => {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}, [pageCounter]);
从 nextPage()
和 prevPage()
中删除 updateTitles()
函数
我想弄清楚这是如何工作的。
我有一个 'pageCounter' 变量用于跟踪当前页面(在 prev/next 按钮单击时更新),当它更新时,我想将选项卡的标题更改为新页面数据.
当我单击下一步按钮时,它不会呈现,除非我单击它两次并且控制台日志显示它尚未更新。但是当我点击下一步后点击我的 'log' 按钮时,它说它已经更新了?
我进行了研究并假设这是由于 'setState' 函数的异步性质造成的。但是,我不确定如何解决这个问题?
我尝试将 updateTitles 函数放入 useEffect
钩子中,但无论是将函数的内容复制到其中,还是调用钩子中的函数,都会出现错误。
我错过了什么?
将 updateTitles
的内容放入 useEffect
时出现的错误是:
Maximum Update Depth Exceeded.
组件代码如下:(code sandbox here)
import React from "react";
import "./styles.css";
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Blah1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "MrMagoo",
Option2: "Nins",
Option3: "Pottao"
};
function updateTitles() {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}
function nextPage() {
if (pageCounter < 3) {
setPage(pageCounter + 1);
updateTitles();
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1);
updateTitles();
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={prevPage} id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{}</p>
<button onClick={nextPage} id="next">
Next
</button>
<button onClick={printLog} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
这是我尝试改用钩子 useEffect 时的代码,但我收到一条错误消息 "Maximum Update Depth Exceeded"。
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "Page 1.11",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "Page 1.1",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Page 2.1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "Page 3.1",
Option2: "Nins",
Option3: "Pottao"
};
useEffect(() => {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}, [pageCounter, pageOneTitles, pageTwoTitles, pageThreeTitles]);
function nextPage() {
if (pageCounter < 3) {
setPage(pageCounter + 1);
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1);
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={prevPage} id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{pageCounter}</p>
<button onClick={nextPage} id="next">
Next
</button>
<button onClick={printLog} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
这是 useEffect 挂钩的代码沙箱:https://codesandbox.io/s/thirsty-panini-mkdzh
我认为这应该可行:
import React, { useState, useEffect } from "react";
function Options() {
// Component States
const [pageCounter, setPage] = useState(1);
const [optionTitles, setOptionTitles] = useState({
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
});
//Component Variables
const pageOneTitles = {
Option1: "End of Lease Clean",
Option2: "Regular House Cleaning",
Option3: "Other Clean"
};
const pageTwoTitles = {
Option1: "Blah1",
Option2: "Blah12",
Option3: "Blah13"
};
const pageThreeTitles = {
Option1: "MrMagoo",
Option2: "Nins",
Option3: "Pottao"
};
function updateTitles() {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}
function nextPage() {
if (pageCounter < 3) {
setPage(prev => prev + 1, updateTitles());
console.log(pageCounter);
}
}
function prevPage() {
if (pageCounter > 1) {
setPage(pageCounter - 1, updateTitles());
console.log(pageCounter);
}
}
function printLog() {
console.log(pageCounter);
}
return (
<div id="options">
<button onClick={() => prevPage() } } id="next">
Back
</button>
<CardOption title={optionTitles.Option1} />
<CardOption title={optionTitles.Option2} />
<CardOption title={optionTitles.Option3} />
<p>{}</p>
<button onClick={() => { nextPage() }} id="next">
Next
</button>
<button onClick={() => { printLog() }} id="next">
log
</button>
</div>
);
}
function CardOption(props) {
return (
<div className="card">
<h2>{props.title}</h2>
</div>
);
}
export default Options;
onClick
应该传递一个回调来调用函数而不是调用它。
此外,我没有看到您在代码段
useEffect
useEffect
运行s。确保将其设置为
useEffect(()=> {
// do stuff with pagecounter , which is updated count
},[pageCount])
如果你想运行它只安装一次
useEffect(()=> {
// do stuff with pagecounter , which is initial count
},[])
useEffect 也在第一次渲染时 运行s,避免 运行在初始渲染时使用
const [pageCount, setPageCount] = useState(0)
useEffect(()=> {
if (pageCount===0){
//this prevent to run on first render
return
}
// code here will only run on updating state
},[pageCount])
结合useEffect()
和useCallback()
函数。
useEffect(()=> {
updateTitles();
},[pageCounter]);
const updateTitles = useCallback(() => {
switch (pageCounter) {
case 1:
setOptionTitles(pageOneTitles);
break;
case 2:
setOptionTitles(pageTwoTitles);
break;
case 3:
setOptionTitles(pageThreeTitles);
break;
default:
console.log("default");
break;
}
}, [pageCounter]);
从 nextPage()
和 prevPage()
updateTitles()
函数