反应渲染疯狂
React render madness
我正在使用 React 挂钩和功能组件。在我的功能组件中,我发生了一些奇怪的事情,我无法找到解决办法。在 useEffect 中,最初我没有 return 数组来防止无限循环,并试图在 deleteClickedHandler 中使用 rowData 但它始终为空。在一些研究表明解决这个问题的方法是使用 useRef 之后,这似乎可行但引发了 ESLinter 的愤怒,它要求将 rowData 放在数组中,这会导致重新呈现 useEffect。这会导致 deleteClickedHandler 从 rowDataRef.current 接收数据,但会导致无限循环。
deleteClickedHandler 正在执行开放式并发、更改 rowData 状态并与 api 交互。
几个小时后,我不知道如何解决这个问题。
如果我从数组中删除告诉 useEffect 何时重新呈现的 rowData,删除处理程序会工作但不会重新呈现,并且由于 deleteClickedHandler 是一个处理程序,我无法确定如何在没有的情况下重新呈现无限循环。
我确定我在做一些愚蠢的事情,但无法确定为什么 rowData 在 deleteClickedHandler 中不可用 - 我知道处理程序是一种闭包形式,但 rowData 是状态。
const initialState = {
id: 0,
credit: false,
transactionAmount: 0,
accountBalance: 0,
transactionDate: new Date(),
confirmation: "",
comment: "",
action: "EDIT",
};
const SERVER_URL='/api/checking'; //process.env.REACT_APP_SERVER_URL;
function Checking() {
const [rowData, setRowData] = useState([]);
const [newData, setNewData] = useState(initialState);
const [displayModal, setModalDisplay] = useState(false);
const columnDefinitions = Columns();
const rowDataRef = useRef(rowData);
useEffect(() => {
fetch(SERVER_URL)
.then((response) => response.json())
.then((rowData) => setRowData(rowData));
rowDataRef.current = rowData;
}, [rowData]);
function deleteClickedHandler(props) {
let fetchUrl = SERVER_URL + "/" + props.id;
let balance = 0.0;
let transactionAmount = 0.0;
let data = rowDataRef.current;
if (
data.length > 0 &&
window.confirm("Are you sure you wish to delete transaction: " + props.id)
) {
for (let i = 0; i < data.length; i++) {
transactionAmount = props.credit
? props.transactionAmount
: -1.0 * props.transactionAmount;
balance = balance + transactionAmount;
if (data[i].id === props.id) {
data.splice(i, 1);
}
if (data[i].id > props.id) {
data[i].accountBalance = balance;
}
}
setRowData(data);
CustomFetch(fetchUrl, "DELETE");
}
}
function rowActionHandler(props) {
switch (props.action) {
case "DELETE":
deleteClickedHandler(props);
break;
default:
break;
}
}
const context = { componentParent: rowActionHandler };
编辑 1
以下清理无限渲染并允许删除通过rowDataRef访问rowData,但删除后不会重新渲染。如何让删除后的重新渲染生效?
useEffect(() => {
fetch(SERVER_URL)
.then((response) => response.json())
.then((rowData) => {
setRowData(rowData)
rowDataRef.current = rowData;
});
}, []);
虽然不理想,但有一个解决方法,与我手动执行的操作相同。这是为了使用下面的语句强制页面重新加载。如果有人可以提供状态方法,我愿意改变这个答案。
window.location.reload();
我正在使用 React 挂钩和功能组件。在我的功能组件中,我发生了一些奇怪的事情,我无法找到解决办法。在 useEffect 中,最初我没有 return 数组来防止无限循环,并试图在 deleteClickedHandler 中使用 rowData 但它始终为空。在一些研究表明解决这个问题的方法是使用 useRef 之后,这似乎可行但引发了 ESLinter 的愤怒,它要求将 rowData 放在数组中,这会导致重新呈现 useEffect。这会导致 deleteClickedHandler 从 rowDataRef.current 接收数据,但会导致无限循环。
deleteClickedHandler 正在执行开放式并发、更改 rowData 状态并与 api 交互。
几个小时后,我不知道如何解决这个问题。
如果我从数组中删除告诉 useEffect 何时重新呈现的 rowData,删除处理程序会工作但不会重新呈现,并且由于 deleteClickedHandler 是一个处理程序,我无法确定如何在没有的情况下重新呈现无限循环。
我确定我在做一些愚蠢的事情,但无法确定为什么 rowData 在 deleteClickedHandler 中不可用 - 我知道处理程序是一种闭包形式,但 rowData 是状态。
const initialState = {
id: 0,
credit: false,
transactionAmount: 0,
accountBalance: 0,
transactionDate: new Date(),
confirmation: "",
comment: "",
action: "EDIT",
};
const SERVER_URL='/api/checking'; //process.env.REACT_APP_SERVER_URL;
function Checking() {
const [rowData, setRowData] = useState([]);
const [newData, setNewData] = useState(initialState);
const [displayModal, setModalDisplay] = useState(false);
const columnDefinitions = Columns();
const rowDataRef = useRef(rowData);
useEffect(() => {
fetch(SERVER_URL)
.then((response) => response.json())
.then((rowData) => setRowData(rowData));
rowDataRef.current = rowData;
}, [rowData]);
function deleteClickedHandler(props) {
let fetchUrl = SERVER_URL + "/" + props.id;
let balance = 0.0;
let transactionAmount = 0.0;
let data = rowDataRef.current;
if (
data.length > 0 &&
window.confirm("Are you sure you wish to delete transaction: " + props.id)
) {
for (let i = 0; i < data.length; i++) {
transactionAmount = props.credit
? props.transactionAmount
: -1.0 * props.transactionAmount;
balance = balance + transactionAmount;
if (data[i].id === props.id) {
data.splice(i, 1);
}
if (data[i].id > props.id) {
data[i].accountBalance = balance;
}
}
setRowData(data);
CustomFetch(fetchUrl, "DELETE");
}
}
function rowActionHandler(props) {
switch (props.action) {
case "DELETE":
deleteClickedHandler(props);
break;
default:
break;
}
}
const context = { componentParent: rowActionHandler };
编辑 1
以下清理无限渲染并允许删除通过rowDataRef访问rowData,但删除后不会重新渲染。如何让删除后的重新渲染生效?
useEffect(() => {
fetch(SERVER_URL)
.then((response) => response.json())
.then((rowData) => {
setRowData(rowData)
rowDataRef.current = rowData;
});
}, []);
虽然不理想,但有一个解决方法,与我手动执行的操作相同。这是为了使用下面的语句强制页面重新加载。如果有人可以提供状态方法,我愿意改变这个答案。
window.location.reload();