У меня есть пользователь, у которого есть данные на странице в этой форме:
[{ 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 }]
Я хотел бы узнать, как получить разницу между новыми и старыми данными. Затем добавьте или удалите нужный объект из массива состояний, а не полностью сбросьте состояние. Используемый идентификатор всегда будет уникальным.
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}]
}))
}
Но найти разницу между старыми и новыми данными таким способом не очень приятно. Я пробовал решения из Сравните 2 массива, которые возвращают разницу , но я не смог заставить его работать. Я надеюсь, что вы можете помочь мне представить лучший способ найти разницу. В приведенном выше примере я использовал 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>
);
}
}