TypeError:无法通过useEffect和Tabulator读取未定义的属性''

时间:2020-02-21 14:08:56

标签: javascript reactjs tabulator

这里是codesandbox for the problem

该示例包括三个部分:

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

一切正常,直到row is clicked in the grid library

我收到此错误。

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() {

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


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>
)

1 个答案:

答案 0 :(得分:0)

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