【发布时间】:2018-04-27 15:23:04
【问题描述】:
我有一个用户在这个表单的页面上有一些数据:
[{ name: 'Jack', id: 1 }, { name: 'Ellen', id: 2 }, {name: 'Nick', id: 3}]
Apollo 查询会加载此数据。用户可以使用表单向页面添加名称或从页面中删除名称。 Apollo 突变处理添加或删除请求。 RefetchQueries 在突变后被调用,状态被更新并且名称列表被重新呈现。
问题是,如果我添加一个名称,refetchQueries 将返回所有 4 个对象,作为回报,所有 4 个对象都设置为状态。
[{ name: 'Jack', id: 1 }, { name: 'Ellen', id: 2 }, {name: 'Nick', id: 3}, { name: 'Mary', id: 4 }]
我想了解如何获取新旧数据之间的差异。然后从状态数组中添加或删除正确的对象,而不是完全重置状态。使用的 id 将始终是唯一的。
loadData = (names, that) => {
that.setState({ loading:true });
let data = {};
data.names= [];
const oldNames = that.state.names;
names.map(name=> (
data.names.push({ name: name.name, id: name.id })
));
that.setState({names: data.names, loading: false });
}
上面的函数在 componentWillUpdate 中被这样调用:
componentWillUpdate(nextProps, nextState) {
loadData(nextProps.names, this);
}
我正在尝试更改此功能如下:
updateData = (names, that) => {
let data = {};
data.names = [];
const oldNames = that.state.names ;
names.map(name => (
data.names.push({ name: name.name, id: name.id })
));
let difference = _(data.names)
.differenceBy(oldNames, 'id', 'name')
.map(_.partial(_.pick, _, 'id', 'name'))
.value();
if (data.names.length > oldNames.length)
that.setState(prevState => ({
names: [...prevState.names, {name: difference[0].name, id: difference[0].id}]
}))
}
但是用这种方式找到新旧数据的差异,感觉不是很好。我已经尝试了Compare 2 arrays which returns difference 的解决方案,但我无法让它工作。我希望你能帮助我介绍一种更好的方法来找到差异。在上面的示例中,我使用了 lodash,但这不是必需的。我也想知道有没有更好的方法。例如,直接从 Apollo 突变中获取结果并将此结果添加到 State。
更新节点映射:
render() {
if (this.state.loading) { return <div>Loading...</div> }
const links = this.state.links.map( (link,i) => {
return (
<Link
linkClass={this.props.linkClass}
key={link.target+i}
data={link}
/>);
});
const nodes = this.state.nodes.map( (node) => {
return (
<Node
nodeClass={this.props.nodeClass}
data={node}
label={node.label}
key={node.id}
onClick={this.onClickHandler.bind(this, node)}
/>);
});
return (
<div className="graphContainer">
<svg className="graph" width={FORCE.width} height={FORCE.height}>
<g >
{links}
</g>
<g >
{nodes}
</g>
</svg>
</div>
);
}
}
【问题讨论】:
-
您希望实现什么目标?根据您编写的代码,不会有任何性能提升,因为所有使用
this.state.names的组件都将重新渲染。如果你想减少 API 调用的负载大小,那么我有一些想法。 -
使用 d3 显示名称。因此,如果我重新加载整个状态,整个 d3 图就会重新渲染。我只想在 d3 图中添加或删除单个元素。起初我也想找到一种方法来使用 Javascript 来获得差异,但我不知道如何找到它。我想让这部分工作,但任何性能提升都会得到真正的赞赏
-
添加你使用
this.state.names的代码和图形组件。 -
this.state.names在加载/更新数据时使用,并且仅用于初始化力。我不确定如何显示所有图形代码,它在少数不同的组件中有 300 多行。你在找什么? -
问题是,我不确定上面的 lodash 代码中发生了什么,我真的想返回新旧对象数组之间的差异。当我添加名称时,上面的代码有效。但是,如果我删除一个名称,则不会返回已删除的对象。稍后,用户可能会添加或删除多个名称或编辑对象。这段 lodash 代码无法解决所有这些问题。所以我想知道如何获取添加、删除或编辑的对象。我觉得 d3 图表并不是该问题的一部分,如果我错了或没有足够清楚地提出问题,请原谅。
标签: javascript reactjs apollo