Maison  >  Questions et réponses  >  le corps du texte

La fonctionnalité de rétablissement pour les enregistrements d'entité ne définit pas correctement le statut

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粉029057928P粉029057928420 Il y a quelques jours770

répondre à tous(1)je répondrai

  • P粉729518806

    P粉7295188062023-09-16 11:56:23

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

    répondre
    0
  • Annulerrépondre