首页 > 解决方案 > TypeError:无法通过 useEffect 和 Tabulator 读取未定义的属性“”

问题描述

这是问题的代码框

该示例包含三个部分:

一个 useEffect 实例化网格,而另一个则监听状态变化以更新网格。

一切正常,直到在网格库中单击一行

我得到这个错误。

TypeError: Cannot read property 'companyName' of undefined

  471 | id={"input-companyName"}
  472 | list={"options-companyName"}
  473 | className={"form-input"}
> 474 | value={formJournalItems.companyName}
  475 | onChange={handleDatalistChange}
  476 | onKeyUp={handleKeyUp}
  477 | ref={refCompanyName}


  325 | 
  326 |    function handleTableRowClick(journalItemId) {
  327 |        let journalItem = journalItems.filter(item => item.id === journalItemId)[0]
> 328 |        setFormJournalItems(journalItem)
  329 |    }
  330 | 
  331 |    function isValidFormInputs() {

这是有问题的代码,其余的可以在codeandbox中看到。


let refCompanyName = React.createRef();

let refTable = useRef(null);
let table = useRef(null);

const [journalItems, setJournalItems] = useState([]);

const initialFormJournalItems = {
        id: "",
        journalId: "",
        companyId: "",
        companyName: "",
        documentKey: "",
        documentDate: "",
        debitAccountId: "",
        debitAccount: "",
        debit: "",
        creditAccountId: "",
        creditAccount: "",
        credit: ""
    }

const [formJournalItems, setFormJournalItems] = useState(initialFormJournalItems);

useEffect(() => {

    fetch(`http://localhost:4000/journals/${props.match.params.key}/items`)
            .then(res => res.json())
            .then(data => {
                setJournalItems(data)
            })
            .catch(err => err);

         table.current = new Tabulator(refTable.current, {
            data: journalItems,
            height: "100%",
            layout: "fitColumns",
            rowClick: function (e, row) {
                //e - the click event object
                //row - row component
                console.log("tabulator journalitems", journalItems) // <------ EMPTY []
                console.log(row._row.data)
                handleTableRowClick(row._row.data.id)
            },
            columns: [
                { title: "Компанија", field: "companyName" },
                { title: "Документ", field: "documentKey" },
                { title: "Датум", field: "documentDate" },
                { title: "Должи", field: "debitAccount" },
                { title: "Износ", field: "debit" },
                { title: "Побарува", field: "creditAccount" },
                { title: "Износ", field: "credit" },
            ],
        });

    }, []);

// Updates the tabulator table on item change
    useEffect(() => {
        console.log("useEffect journalItems", journalItems) // <------ POPULATED
        console.log("useEffect refTable", refTable)
        console.log("useEffect table", table)
        table.current.replaceData(journalItems)
    }, [journalItems]);

function handleTableRowClick(journalItemId) {
    let journalItem = journalItems.filter(item => item.id === journalItemId)[0]
    setFormJournalItems(journalItem)
}

return (
    <div>
        <input
            type={"text"}
            name={"companyName"}
            id={"input-companyName"}
            list={"options-companyName"}
            className={"form-input"}
            value={formJournalItems.companyName}
            onChange={handleDatalistChange}
            onKeyUp={handleKeyUp}
            ref={refCompanyName}
            multiple
         />
    </div>
)

标签: javascriptreactjstabulator

解决方案


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

推荐阅读