useState钩子-状态丢失,即重置为初始值

时间:2020-02-22 04:07:25

标签: javascript reactjs react-hooks use-effect

我正在尝试在安装周期中初始化状态,然后在每次更新时对其进行操作。

但是,状态会以某种方式重置吗?我不明白为什么。

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 []

2 个答案:

答案 0 :(得分:1)

我设法用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]);

答案 1 :(得分:1)

我相信这是因为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]);

别忘了更新第一个效果的依赖项数组。效果内部引用的所有外部作用域变量都必须在此数组中。