嵌套可观察更改时组件不重新渲染
Component not re-rendering when nested observable changes
将节点添加到列表,但组件未重新呈现。 Mobx Chrome 扩展开发工具说它是一个依赖项,但出于某种原因仍然没有反应!
按钮根据节点是否在列表中呈现 'Add' 或 'Remove'。它不会重新呈现,除非我移动到另一个组件然后再次打开该组件。
按钮:
@inject("appStore") @observer
class EntityTab extends Component {
...
render() {
return (
...
{/* BUTTONS */}
{ this.props.appStore.repo.canvas.graph.structure.dictionary[id] !== undefined ?
<div onClick={() => this.props.appStore.repo.canvas.graph.function(id)}>
<p>Remove</p>
</div>
:
<div onClick={() => this.props.appStore.currRepo.canvas.otherfunction(id)}>
<p>Add</p>
</div>
}
...
)
}
}
添加按钮呈现,我点击触发的按钮
this.props.appStore.currRepo.canvas.otherfunction(id)
然后我们进入这个功能
@observable graph = new Graph();
...
@action
otherfunction = (idList) => {
// Do nothing if no ids are given
if (idList === null || (Array.isArray(idList) && idList.length === 0)) return;
// If idList is a single value, wrap it with a list
if (!Array.isArray(idList)) { idList = [idList] }
let nodesToAdd = [];
let linksToAdd = [];
// Add all new links/nodes to graph
Promise.all(idList.map((id) => { return this.getNode(id, 1) }))
.then((responses) => {
for (let i = 0; i < responses.length; i++) {
let res = responses[i];
if (res.success) {
nodesToAdd.push(...res.data.nodes);
linksToAdd.push(...res.data.links);
}
}
this.graph.addData(nodesToAdd, linksToAdd, idList, this.sidebarVisible);
});
};
getNode 函数根据数据创建新的 Node 对象。作为参考,这些对象是这样实例化的
export default class Node {
id = '';
name = '';
type = '';
constructor(r) {
for (let property in r) {
// Set Attributes
this[property] = r[property];
}
}
}
无论如何,addToGraphFromIds 触发
this.graph.addData(nodesToAdd, linksToAdd);
然后我们转到那个函数
@action
addData = (nodes, links) => {
this.structure.addNodes(nodes);
this.structure.addLinks(links);
};
哪个触发
this.structure.addNodes(nodes);
导致这个函数
@observable map = new Map();
@observable map2 = new Map();
@observable dictionary = {};
@observable dictionary2 = {};
@observable allNodes = [];
@observable allLinks = [];
...
@action
addNodes = (nodes=[]) => {
if (!nodes || nodes.length === 0) return;
nodes = utils.toArray(nodes);
// Only consider each new node if it's not in the graph or a duplicate within the input list
nodes = _.uniqBy(nodes, (obj) => { return obj.id; });
const nodesToConsider = _.differenceBy(nodes, this.allNodes, (obj) => { return obj.id; });
// Add nodes to map
let currNode;
for (let i = 0; i < nodesToConsider.length; i++) {
currNode = nodesToConsider[i];
this.map.set(currNode.id, new Map());
this.map2.set(currNode.id, new Map());
this.dictionary[currNode.id] = currNode;
}
// Update internal list of nodes
this.allNodes = this.allNodes.concat(nodesToConsider);
};
正如我们在第一个代码框中看到的那样,
this.props.appStore.repo.canvas.graph.structure.dictionary[id] !== undefined
应该会导致按钮在我们添加当前节点时更改值。当我登录或使用 mobx chrome 扩展开发工具时,节点出现在字典中,但我必须切换选项卡,然后按钮将重新呈现。我试过使用其他行,例如
this.props.appStore.repo.canvas.graph.structure.allNodes.includes(node)
但这也不管用。我绝对卡住了,需要帮助。我有一种感觉,它与嵌套的可观察对象有关,也许标记 @observable 不够好,但不太确定。 repo 和 canvas 被标记为可观察对象并实例化一个新的 Repo() 对象和新的 Canvas() 对象,很像在 getNodes.
中创建的 new Node()
看起来 Edward 解决了它,类似于 Redux 看起来你必须用字典创建一个新对象而不是修改它。我猜这是因为键 currNode.id 已经被定义(因为值未定义),我们只是将它修改为 currNode。这是我的猜测,不管它现在是否有效。
除非使用 observable.map
,否则 Mobx (v4) 不会跟踪可观察对象中条目的添加或删除。或者升级到 mobx v5
应该可以解决问题。
对于您的具体问题,您可以尝试:
@observable nodeIdToNodeData = {};
//...
this.nodeIdToNodeData = {...this.nodeIdToNodeData, [currNode.id]: currNode};
或尝试升级到mobx v5
。
更多信息here
将节点添加到列表,但组件未重新呈现。 Mobx Chrome 扩展开发工具说它是一个依赖项,但出于某种原因仍然没有反应!
按钮根据节点是否在列表中呈现 'Add' 或 'Remove'。它不会重新呈现,除非我移动到另一个组件然后再次打开该组件。
按钮:
@inject("appStore") @observer
class EntityTab extends Component {
...
render() {
return (
...
{/* BUTTONS */}
{ this.props.appStore.repo.canvas.graph.structure.dictionary[id] !== undefined ?
<div onClick={() => this.props.appStore.repo.canvas.graph.function(id)}>
<p>Remove</p>
</div>
:
<div onClick={() => this.props.appStore.currRepo.canvas.otherfunction(id)}>
<p>Add</p>
</div>
}
...
)
}
}
添加按钮呈现,我点击触发的按钮
this.props.appStore.currRepo.canvas.otherfunction(id)
然后我们进入这个功能
@observable graph = new Graph();
...
@action
otherfunction = (idList) => {
// Do nothing if no ids are given
if (idList === null || (Array.isArray(idList) && idList.length === 0)) return;
// If idList is a single value, wrap it with a list
if (!Array.isArray(idList)) { idList = [idList] }
let nodesToAdd = [];
let linksToAdd = [];
// Add all new links/nodes to graph
Promise.all(idList.map((id) => { return this.getNode(id, 1) }))
.then((responses) => {
for (let i = 0; i < responses.length; i++) {
let res = responses[i];
if (res.success) {
nodesToAdd.push(...res.data.nodes);
linksToAdd.push(...res.data.links);
}
}
this.graph.addData(nodesToAdd, linksToAdd, idList, this.sidebarVisible);
});
};
getNode 函数根据数据创建新的 Node 对象。作为参考,这些对象是这样实例化的
export default class Node {
id = '';
name = '';
type = '';
constructor(r) {
for (let property in r) {
// Set Attributes
this[property] = r[property];
}
}
}
无论如何,addToGraphFromIds 触发
this.graph.addData(nodesToAdd, linksToAdd);
然后我们转到那个函数
@action
addData = (nodes, links) => {
this.structure.addNodes(nodes);
this.structure.addLinks(links);
};
哪个触发
this.structure.addNodes(nodes);
导致这个函数
@observable map = new Map();
@observable map2 = new Map();
@observable dictionary = {};
@observable dictionary2 = {};
@observable allNodes = [];
@observable allLinks = [];
...
@action
addNodes = (nodes=[]) => {
if (!nodes || nodes.length === 0) return;
nodes = utils.toArray(nodes);
// Only consider each new node if it's not in the graph or a duplicate within the input list
nodes = _.uniqBy(nodes, (obj) => { return obj.id; });
const nodesToConsider = _.differenceBy(nodes, this.allNodes, (obj) => { return obj.id; });
// Add nodes to map
let currNode;
for (let i = 0; i < nodesToConsider.length; i++) {
currNode = nodesToConsider[i];
this.map.set(currNode.id, new Map());
this.map2.set(currNode.id, new Map());
this.dictionary[currNode.id] = currNode;
}
// Update internal list of nodes
this.allNodes = this.allNodes.concat(nodesToConsider);
};
正如我们在第一个代码框中看到的那样,
this.props.appStore.repo.canvas.graph.structure.dictionary[id] !== undefined
应该会导致按钮在我们添加当前节点时更改值。当我登录或使用 mobx chrome 扩展开发工具时,节点出现在字典中,但我必须切换选项卡,然后按钮将重新呈现。我试过使用其他行,例如
this.props.appStore.repo.canvas.graph.structure.allNodes.includes(node)
但这也不管用。我绝对卡住了,需要帮助。我有一种感觉,它与嵌套的可观察对象有关,也许标记 @observable 不够好,但不太确定。 repo 和 canvas 被标记为可观察对象并实例化一个新的 Repo() 对象和新的 Canvas() 对象,很像在 getNodes.
中创建的 new Node()看起来 Edward 解决了它,类似于 Redux 看起来你必须用字典创建一个新对象而不是修改它。我猜这是因为键 currNode.id 已经被定义(因为值未定义),我们只是将它修改为 currNode。这是我的猜测,不管它现在是否有效。
除非使用 observable.map
,否则 Mobx (v4) 不会跟踪可观察对象中条目的添加或删除。或者升级到 mobx v5
应该可以解决问题。
对于您的具体问题,您可以尝试:
@observable nodeIdToNodeData = {};
//...
this.nodeIdToNodeData = {...this.nodeIdToNodeData, [currNode.id]: currNode};
或尝试升级到mobx v5
。
更多信息here