useState 钩子 - 状态丢失,即重置为初始值
useState hook - state gets lost i.e. resets to initial value
我试图在安装周期中初始化状态,然后在每次更新时对其进行一些处理。
但是,状态会以某种方式重置?我不明白为什么。
const [journalItems, setJournalItems] = useState([]);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
table.current = new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems) // State is lost returns []
handleTableRowClick(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, []);
useEffect(() => {
console.log("useEffect journalItems", journalItems) // Works fine
table.current.replaceData(journalItems) // Uses the new state
}, [journalItems]);
function handleTableRowClick(journalItemId) {
console.log("handletablerowclick journalitems", journalItems) // State is lost, resets to []
}
结果来自控制台日志...
useEffect journalItems []
useEffect journalItems (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
tabulator journalitems []
handleTableRowClick journalitems []
我设法以一种奇怪的方式解决了这个问题,使用 useRef
作为函数变量,并将函数定义移动到 useEffect
?
const [journalItems, setJournalItems] = useState([]);
let handleTableRowClick = useRef(null);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
table.current = new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems) // State is lost returns []
handleTableRowClick.current(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, []);
useEffect(() => {
console.log("useEffect journalItems", journalItems) // Works fine
table.current.replaceData(journalItems) // Uses the new state
handleTableRowClick.current = (journalItemId) => {
console.log("handletablerowclick journalItems", journalItems)
// Find the clicked row from all the rows
let journalItem = journalItems.filter(item => item.id === journalItemId)[0]
setFormJournalItems(journalItem)
}
}, [journalItems]);
我相信这是因为 journalItems
的初始值在为 rowClick
属性.
定义的函数内部被关闭
因为包含 table.current
的效果只有 运行 一次,所以 table.current
值获得所有初始值并且永远不会使用 rowClick
属性的新处理程序更新.
我怀疑您可能需要进行以下更改才能使事情顺利进行:
const [journalItems, setJournalItems] = useState([]);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
}, [props.match.params.key]);
// Re-create a new `table.current` value (including all handlers) when `journalItems` changes
table.current = useMemo(() => {
return new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems)
handleTableRowClick(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, [journalItems]);
useEffect(() => {
console.log("useEffect journalItems", journalItems)
table.current.replaceData(journalItems)
}, [journalItems]);
const handleTableRowClick = useCallback((journalItemId) => {
console.log("handletablerowclick journalitems", journalItems);
}, [journalItems]);
不要忘记更新第一个效果的依赖数组。您的效果中引用的外部作用域中的所有变量都必须在此数组中。
我试图在安装周期中初始化状态,然后在每次更新时对其进行一些处理。
但是,状态会以某种方式重置?我不明白为什么。
const [journalItems, setJournalItems] = useState([]);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
table.current = new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems) // State is lost returns []
handleTableRowClick(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, []);
useEffect(() => {
console.log("useEffect journalItems", journalItems) // Works fine
table.current.replaceData(journalItems) // Uses the new state
}, [journalItems]);
function handleTableRowClick(journalItemId) {
console.log("handletablerowclick journalitems", journalItems) // State is lost, resets to []
}
结果来自控制台日志...
useEffect journalItems []
useEffect journalItems (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
tabulator journalitems []
handleTableRowClick journalitems []
我设法以一种奇怪的方式解决了这个问题,使用 useRef
作为函数变量,并将函数定义移动到 useEffect
?
const [journalItems, setJournalItems] = useState([]);
let handleTableRowClick = useRef(null);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
table.current = new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems) // State is lost returns []
handleTableRowClick.current(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, []);
useEffect(() => {
console.log("useEffect journalItems", journalItems) // Works fine
table.current.replaceData(journalItems) // Uses the new state
handleTableRowClick.current = (journalItemId) => {
console.log("handletablerowclick journalItems", journalItems)
// Find the clicked row from all the rows
let journalItem = journalItems.filter(item => item.id === journalItemId)[0]
setFormJournalItems(journalItem)
}
}, [journalItems]);
我相信这是因为 journalItems
的初始值在为 rowClick
属性.
因为包含 table.current
的效果只有 运行 一次,所以 table.current
值获得所有初始值并且永远不会使用 rowClick
属性的新处理程序更新.
我怀疑您可能需要进行以下更改才能使事情顺利进行:
const [journalItems, setJournalItems] = useState([]);
useEffect(() => {
fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
.then(res => res.json())
.then(data => {
setJournalItems(data) // Sets the state when the AJAX completes
})
.catch(err => err);
}, [props.match.params.key]);
// Re-create a new `table.current` value (including all handlers) when `journalItems` changes
table.current = useMemo(() => {
return new Tabulator(refTable.current, {
rowClick: function (e, row) {
console.log("tabulator journalitems", journalItems)
handleTableRowClick(row._row.data.id)
},
columns: [
{ title: "Компанија", field: "companyName" },
{ title: "Документ", field: "documentKey" },
],
});
}, [journalItems]);
useEffect(() => {
console.log("useEffect journalItems", journalItems)
table.current.replaceData(journalItems)
}, [journalItems]);
const handleTableRowClick = useCallback((journalItemId) => {
console.log("handletablerowclick journalitems", journalItems);
}, [journalItems]);
不要忘记更新第一个效果的依赖数组。您的效果中引用的外部作用域中的所有变量都必须在此数组中。