La fonctionnalité de rétablissement pour les enregistrements d'entité ne définit pas correctement le statut
P粉029057928
P粉029057928 2023-09-15 19:27:41
0
1
804

Je construis une application de cartographie mentale à l'aide d'enregistrements d'entités. Les données de l'application sont un arbre de nœuds et je souhaite pouvoir reparenter les nœuds via annuler/rétablir. Le problème auquel je suis confronté est que même si l’opération d’annulation fonctionne correctement, l’opération de rétablissement ne fonctionne pas.

J'ai recréé mon problème dans une application simple :

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;

Lorsque le bouton "Changer parent de 3" est cliqué, la fonction changeState :

  1. Supprimer le nœud 3 de sa liste enfants parent (nœud 0)
  2. Ajouter le nœud 3 à sa nouvelle liste de nœuds enfants du nœud parent (nœud 2)
  3. Réinitialiser le nœud parent du nœud 3 à 2

Rework restaure correctement l'état à sa valeur initiale, les colonnes 1,2,3 étant les enfants de 0.

Mais Redo définit la liste des nœuds enfants du nœud 0 à 3 alors qu'il devrait la définir à 1,2 ! Très étrangement, cela n'arrive pas si je ne définis pas la propriété Parentis du nœud 3, qui n'est pas directement liée à la propriété Children du nœud 0...

Je soupçonne qu'il s'agit d'un problème de type référence/valeur, ou peut-être d'un bug dans l'enregistrement de l'entité... De l'aide?

P粉029057928
P粉029057928

répondre à tous(1)
P粉729518806

Comme je m'en doutais, la question est une question de référence... Lors de la première opération, utilisez la fonction "recherche" n => n.id === node.parentid pour sélectionner le bon élément du tableau. Cependant, la manière dont solid-record stocke l'historique des commandes est telle qu'il ne stocke que les objets « nœuds ». Et la propriété parentid du même objet est modifiée par la dernière opération. Le problème a été résolu en utilisant une variable locale qui stocke node.parentid.

Ou, après avoir mieux lu la documentation de l'API du magasin SolidJS, utilisez l'identifiant directement au lieu de la fonction de recherche, comme :

undoHistory.add(setState, node.parentid, 'children', oldparent.children.filter(n => n !== node.id))
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal