我正在使用實體記錄來建立心智圖應用程式。 應用程式中的資料是一棵節點樹,我希望能夠透過撤銷/重做來重新設定節點的父級。 我面臨的問題是,即使撤銷操作工作正常,但重做操作卻不行。
我在一個簡單的應用程式中重新創建了我的問題:
import { Component, For } from 'solid-js' import { createStore } from 'solid-js/store' import { createHistory } from 'solid-record' type Node = { id: number, children: Array<number> parentid: number } const initialValue = [ { id: 0, children: [1, 2, 3], parentid: -1 }, { id: 1, children: [], parentid: 0 }, { id: 2, children: [], parentid: 0 }, { id: 3, children: [], parentid: 0 }, ] const [state, setState] = createStore(initialValue) const undoHistory = createHistory() const changeState = () => { undoHistory.batch() const nodeid = 3 const oldparentid = 0 const newparentid = 2 let node = state[nodeid] let oldparent = state[oldparentid] let newparent = state[newparentid] // first remove node form parent's children undoHistory.add(setState, n => n.id === node.parentid, 'children', oldparent.children.filter(n => n !== node.id)) // then add to new parent's children undoHistory.add(setState, n => n.id === newparent.id, 'children', [...newparent.children, node.id]) // lastly, point to new parent undoHistory.add(setState, n => n.id === node.id, 'parentid', newparent.id) undoHistory.unbatch() } const App: Component = () => { return ( <> <For each={state}>{(node: Node) => <div>{`id: ${node.id}, parentid: ${node.parentid}, children: ${node.children}`}</div>}</For> <button onClick={changeState}>Change Parent of 3</button> <button onClick={() => undoHistory.undo()} disabled={!undoHistory.isUndoable()}>Undo</button> <button onClick={() => undoHistory.redo()} disabled={!undoHistory.isRedoable()}>Redo</button> </> ); }; export default App;
當點擊「更改 3 的父級」按鈕時,changeState 函數:
重做正確地將狀態恢復到其初始值,其中 1,2,3 列為 0 的子級。
但是 Redo 將節點 0 的子節點清單設為 3,而它應該將其設為 1,2! 非常奇怪的是,如果我不設定節點 3 的 Parentis 屬性,則不會發生這種情況,該屬性與節點 0 的 Children 屬性沒有直接關係...
我懷疑這是一個引用與值類型的問題,或者可能是實體記錄中的錯誤... 有什麼幫助嗎?
P粉7295188062023-09-16 11:56:23
正如我所懷疑的,該問題是參考問題... 執行第一個操作時,使用「搜尋」函數 n => n.id === node.parentid 選擇陣列的正確元素。 但是,solid-record 儲存命令歷史的方式使得它只儲存「節點」物件。 並且同一物件的parentid 屬性被最後一個操作修改。 透過使用儲存node.parentid的局部變數解決了這個問題。
或者,在更好地閱讀 SolidJS store API 文件之後,直接使用 id 而不是搜尋功能,例如:
undoHistory.add(setState, node.parentid, 'children', oldparent.children.filter(n => n !== node.id))