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 :
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?
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 :