搜索

首页  >  问答  >  正文

实体记录的重做功能未正确设置状态

我正在使用实体记录来构建思维导图应用程序。 应用程序中的数据是一棵节点树,我希望能够通过撤消/重做来重新设置节点的父级。 我面临的问题是,即使撤消操作工作正常,但重做操作却不行。

我在一个简单的应用程序中重新创建了我的问题:

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. 从其父级(节点 0)子级列表中删除节点 3
  2. 将节点 3 添加到其新的父节点(节点 2)子节点列表
  3. 将节点 3 的父节点重置为 2

重做正确地将状态恢复到其初始值,其中 1,2,3 列为 0 的子级。

但是 Redo 将节点 0 的子节点列表设置为 3,而它应该将其设置为 1,2! 非常奇怪的是,如果我不设置节点 3 的 Parentis 属性,则不会发生这种情况,该属性与节点 0 的 Children 属性没有直接关系...

我怀疑这是一个引用与值类型的问题,或者可能是实体记录中的错误...... 有什么帮助吗?

P粉029057928P粉029057928436 天前781

全部回复(1)我来回复

  • P粉729518806

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

    回复
    0
  • 取消回复