Gui*_*rie 5 javascript separation-of-concerns reactjs redux
我\xe2\x80\x99m 在 React/Redux/Redux Toolkit 中编写了一个非常复杂的应用程序,我遇到了一种情况,我\xe2\x80\x99m 不太确定如何处理。我找到了一种方法来做到这一点,但我\xe2\x80\x99m想知道它是否会导致问题或者是否有更好的方法。简而言之,我希望减速器能够在不修改状态的情况下与调用者进行通信,而我发现的唯一方法是改变操作。
\n描述:
\n为了简化,让\xe2\x80\x99s说我想实现一个水平滚动条(但实际上它\xe2\x80\x99s要复杂得多)。状态包含当前位置、一个介于某些min和max值之间的数字,UI 绘制一个具有该位置并且可以单击并水平拖动的矩形。
主要属性:如果用户单击并拖动的距离超过最小/最大值,则矩形不会进一步移动,但如果用户随后向另一个方向移动,则矩形应等到鼠标回到其原始位置之前开始向后移动(与大多数/所有操作系统上的滚动条行为完全相同)。
\n请记住,我的实际用例要复杂得多,我有十几个类似的情况,有时限制在最小值和最大值之间,有时每 100 像素捕捉一次,有时取决于状态各个部分的更复杂的约束,等等。 \xe2\x80\x99d 就像一个适用于所有此类情况的解决方案,并且保留了 UI 和逻辑之间的分离。
\n限制条件:
\n问题:
\n因此,减速器是唯一知道我们是否达到最小值/最大值的部分,并且减速器通常与应用程序其余部分通信的唯一方式是通过状态,但我不想\xe2\x80\x99 想要传达该信息通过国家。
\n解决方案?
\n我实际上设法找到了一种方法来解决它,这似乎工作得很好,但感觉有些错误:改变减速器中的操作对象。
\n减速器采用“拖动 10 个像素”的动作,意识到它只能拖动 3 个像素,创建一个已拖动 3 个像素的新状态,并向该动作添加一个字段。action.response = 3
然后,在我的自定义挂钩分派“拖动 10 像素”操作后,它会查看action.response返回值的字段,dispatch以了解实际处理了多少内容,并且它会记住与预期值的差异(在本例中,它会记住我们距原始位置 7 个像素)。\n这样,如果在下一次鼠标移动时我们拖动 -9 像素,我的自定义钩子可以将该数字添加到它记住的 7 像素中,并告诉减速器我们只移动了-2 像素。
在我看来,这个解决方案完美地保留了 UI/逻辑的分离:
\nevent.movementX以补偿减速器在之前的操作中没有\xe2\x80\x99t处理的量,然后发送减速器的正确增量。它也可以很好地处理诸如每 100 像素捕捉一次之类的事情。
\n唯一奇怪的是,reducer 改变了操作,我认为这不应该发生,因为它应该是一个纯函数,但到目前为止我无法\xe2\x80\x99 发现任何问题。该应用程序可以正常工作,Redux Toolkit 不会\xe2\x80\x99 抱怨,并且开发工具也可以正常工作。
\n这个解决方案有什么问题吗?
\n还有其他方法可以做到吗?
\n在技术层面上,我可以看到这是如何运作的。但我也同意这感觉“恶心”。 从技术上讲,改变操作本身就属于一种“副作用”,尽管它不会有意义地破坏应用程序的其余部分。
听起来好像这里的关键逻辑更多是在“调度操作”级别。我认为您可能可以getState()在调度之前和之后调用来比较结果,并以这种方式导出所需的额外数据。事实上,这可能是 thunk 的一个很好的用例:
const processDragEvent = (dragAmountPixels: number) => {
return (dispatch, getState) => {
const stateBefore = getState();
dispatch(dragMoved(dragAmountPixels));
const stateAfter = getState();
const actualAmountChanged = selectActualDragAmount(stateBefore, stateAfter);
// can return a result from the thunk
return actualAmountChanged
}
}
// later, in a hook
const useMyCustomDragBehavior = () => {
const dispatch = useDispatch();
const doSomeDragging = (someDragValue: number) => {
const actualAmountDragged = dispatch(processDragEvent (someDragValue));
// do something useful with this info here
}
}
Run Code Online (Sandbox Code Playgroud)
这样,只有 UI 层关心这些变化。
| 归档时间: |
|
| 查看次数: |
142 次 |
| 最近记录: |