最近,我编写了react-redux应用程序,作为React开发人员,我编写了纯净,功能强大且可预测的代码。即使我喜欢这种体验,但我仍然怀疑我的代码是否还不错。
所以我的状态中有一棵树,我需要更新树中的一堆节点。假设树的API提供了纯方法pureUpdate(path, newNode, tree) => newTree
,该方法返回更新了节点的新树。在这种情况下,我的reducer方法可能看起来像
function updateNodes(tree, updateRules) {
updateRules.forEach(updateRule => {
const { path, node } = updateRule;
tree = pureUpdate(path, node, tree);
});
return tree;
}
但是我不确定是否能做到最好。
看起来很讨厌的第一件事是tree = pureUpdate(path, node, tree);
。看起来好像在修改一个参数,不建议这样做,但是我只是在重新分配
参考,不是吗?答案的第二部分对here进行了说明。但是,尽管这种技巧可能没问题,但是in this discussion表示这样的代码可能未经过优化,并且重新分配参数可能会导致性能问题(more info with examples)。对我来说,最简单的解决方法是使用一个额外的变量,该变量将是树的克隆。
function updateNodes(tree, updateRules) {
let newTree = someCloneFunc(tree);
updateRules.forEach(updateRule => {
const { path, node } = updateRule;
newTree = pureUpdate(path, node, newTree);
});
return newTree;
}
问题是,如果我什么都不想念,我的代码仍然纯净,美观,不会引起任何问题。
答案 0 :(得分:3)
如果您完全关心性能,我不会为了避免重新分配参数而克隆tree
。
虽然您可以在此处使用forEach
并重新分配参数,但是reduce
是针对您的用例的正确功能抽象,它通常比forEach
更好,更有用,因为它可以(并且应该)纯粹使用,而forEach
总是与副作用有关。
基于reduce
的解决方案也提出了是否完全克隆和/或重新分配功能参数的问题。
这是一个有效的reduce
解决方案-没有参数重新分配,没有forEach
副作用,也没有理由克隆tree
:
const updateNodes = (tree, updateRules) =>
updateRules.reduce(
(acc, { path, node }) => pureUpdate(path, node, acc),
tree // initialize acc (the accumulator)
)