LO QUE TENGO
Tengo una clase para Parent y una clase para Child .
export class Parent { properties: { x: number}; child: Child; constructor() { this.properties = { x: 1 } this.child = new Child(this.getX); } getX = () => { return this.properties.x; } } class Child { parent_getX:()=>string constructor(parent_getX:()=>string){ this.parent_getX = parent_getX; } } La clase Parent tiene:
properties que almacena un valor numérico llamado x .getX() que simplemente extrae el valor de x del objeto de properties .child que contiene una referencia a un objeto Child . La clase Child solo recibe una referencia a la función getX() de Parent .
LO QUE QUIERO
Mi objetivo es poder actualizar el valor de x y que cada vez que llamo a child.parent_getX() o parent.getX() obtenga el último valor de x .
LO QUE ESTOY VIENDO
Tengo un componente React llamado Example que toma un Parent con un valor x de 1 como estado inicial.
Cada vez que incremento este valor usando setState(...) el valor de x se incrementa pero por alguna razón, parent.getX() y parent.child.parent_getX() siempre siguen devolviendo el valor inicial de x . ¿Qué puedo hacer para mantener la función sincronizada con el objeto principal?
export const Example = () => { const [parent, setParent] = useState(new Parent()); const incrementX = ()=>{ let newParent = { ...parent, properties: { ...parent.properties, x: parent.properties.x + 1 } } setParent(newParent); } return (<> <p> Parent.properties.x = {parent.properties.x} <br/> Parent.getX() = {parent.getX()} <br/> Parent.child.parent_getX() = {parent.child.parent_getX()} </p> <button onClick={incrementX}> Increment </button> </>); }La razón por la que está viendo los valores antiguos es que en incrementX() crea una copia del Parent existente en lugar de instanciar uno nuevo con new () . Por lo tanto, la instancia existente de Child (que hace referencia a la función getX() del padre anterior) se copia, en lugar de instanciarse en el constructor de Parent . De manera similar, el método getX() en sí mismo se copia con this referencia al padre anterior (debido a que es una función de flecha gruesa, this referencia no cambia).
La forma más sencilla de solucionar esto es agregar un constructor de copia a Parent y usarlo en lugar de la sintaxis extendida:
export class Parent { properties: { x: string}; child: Child; constructor(source?: Parent) { this.properties = { x: '1' } this.child = new Child(() => this.getX()); if (source) { this.properties = {...source.properties}; // any additional copy logic goes here } } getX() { return this.properties.x; } }Luego use ese constructor de copia en su componente:
const incrementX = () => { let newParent = new Parent(parent); newParent.properties.x = newParent.properties.x + 1; setParent(newParent); } Tenga en cuenta que una solución aún más fácil sería no copiar el Parent original en absoluto, y simplemente incrementar sus properties.x , pero supongo que necesita una nueva instancia para que se detecte el cambio de estado.