Estoy tratando de crear un componente recursivo que almacene su estado en un objeto observable mobx.
Por alguna razón peculiar, si el observable vincula a otro observable en sus propiedades, el observer hoc de mobx-react-lite no desencadena una nueva representación cuando cambia el estado del observable.
Aquí está el ejemplo, donde los elementos, que tienen más de 1 de profundidad, no se vuelven a renderizar, cuando cambia el estado observable.
... const NodeView = (props: { node: Node }) => { useEffect(() => { autorun(() => { console.log(`(autorun) ${props.node.label} is expanded: ${props.node.expanded}`); // WRONG: when the node is a child of another node, this runs, but the NodeView is not re-rendered }); }, []); console.log(`rerendering ${props.node.label} `); return ( <> <div className="nodeHeader" onClick={action(() => { props.node.expanded = !props.node.expanded; })} > {props.node.label} </div> {props.node.expanded && ( <div className="row"> <div className="offset" /> <div className="column"> {props.node.children.map((child, index) => ( <NodeView key={index} node={child} /> ))} </div> </div> )} </> ); }; export default memo(observer(NodeView));Así es como se crean los objetos observables:
... interface Node { label: string; expanded: boolean; children: Node[]; nonObservedStuff: any; } const turnIntoObservable = (node: Node) => { const children = node.children.map((child) => turnIntoObservable(child)); let observableNode: Node = { ...node, children }; // i'm trying to make observable not all, but only some specific properties observableNode = makeObservable(observableNode, { expanded: true, children: observable.shallow }); return observableNode; }; let rootNodes: Node[] = ... rootNodes = rootNodes.map((node) => turnIntoObservable(node));Aquí está la demostración de codesandbox
¿Por qué el cambio de estado de un observable, que está vinculado por otro observable en sus propiedades, no provoca que se vuelva a renderizar un componente que observa ese observable?
Está exportando el componente del observer ( export default memo(observer(NodeView)); ), pero dentro NodeView está utilizando NodeView que no es un observador
Debe envolverlo con el observador de inmediato, por lo que la versión recursiva también sería reactiva:
const NodeView = observer((props: { node: Node }) => {} Además, memo se aplica automáticamente para todos los componentes del observer , no necesita volver a aplicarlo manualmente.