我正在嘗試創建一個遞回組件,將它的狀態存盤在 mobx 可觀察物件中。
由于某些特殊原因,如果 observable 在其屬性中鏈接另一個 observable,則當 observable 狀態發生變化時,來自mobx-react-lite的observer hoc不會觸發重新渲染。
這是一個例子,當可觀察狀態發生變化時,深度超過 1 的元素不會重新渲染。
...
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));
以下是可觀察物件的創建方式:
...
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));
這是codeandbox演示
為什么改變一個 observable 的狀態,即由它的屬性中的另一個 observable 鏈接,不會導致重新渲染觀察該 observable 的組件?
uj5u.com熱心網友回復:
您正在匯出observer組件 ( export default memo(observer(NodeView));),但在NodeView其內部您使用的是非觀察者NodeView
您需要立即用觀察者包裝它,因此遞回版本也將是被動的:
const NodeView = observer((props: { node: Node }) => {}
此外,memo它會自動應用于所有observer組件,您無需手動重新應用它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/403088.html
標籤:
上一篇:如何檢查我沒有的例外型別?
下一篇:使用鍵從陣列中洗掉重復物件
