简体   繁体   English

React / Redux加载带副作用的数据

[英]React / Redux loading data with side effects

Let's say I have a stub of a booking system. 假设我有预订系统的存根。

When I create a booking, I can search among our customers and select which customer I'm booking. 当我创建预订时,我可以在我们的客户中搜索并选择我预订的客户。 Upon selecting a customer, the associated customer contacts are loaded as a side effect. 在选择客户时,关联的客户联系人被加载为副作用。 As a user, I have to pick one of these contacts for the booking. 作为用户,我必须为预订选择其中一个联系人。

Let's pretend my state shape is something like this: 让我们假装我的状态是这样的:

{
    customer: {id: 1, name: "Dandy Inc"}
    customerContacts: [{id:1, name: "John Doe"},{id:2, name: "John Doe"}]
    customerContactId: 2
}

Upon save, I only save customerId and customerContactId. 保存后,我只保存customerId和customerContactId。

Now let's say I want to edit this booking at a future point in time. 现在让我们说我想在未来的某个时间编辑此预订。

I can either 我也可以

1) Fetch the data I have, and basically "replay" the actions to trigger the side effects that I need (for instance, set the customer and trigger the side effect of loading the customer contacts) or 1)获取我拥有的数据,并基本上“重放”动作以触发我需要的副作用(例如,设置客户并触发加载客户联系人的副作用)或

2) Fetch the data I have, manually load any extra data I need, and then set the complete application state in one go. 2)获取我拥有的数据,手动加载我需要的任何额外数据,然后一次性设置完整的应用程序状态。

What are your thoughts on the best route to proceed? 您对最佳路线有何看法? This is a simplified example, let's say the real world scenario has at least 2-4 additional side effects that need to be triggered. 这是一个简化的例子,假设真实场景至少有2-4个需要触发的副作用。

It sounds like you should generalize the create/loadCustomerBooking functionality to handle if there's a customerContactId or not (very much pseudocode): 这听起来像你应当概括了create/loadCustomerBooking功能来处理,如果有一个customerContactId或没有(很伪代码):

populateCustomerBooking = (customerId, customerContactId) =>
    loadContacts(customerId)
    if (customerContactId) 
        setContactWithSideEffects(customerContactId)
    runOtherCustomerSideEffects(customerId)
    // And so on...

// This is called when a contact is chosen or we're loading.
setContactWithSideEffects = (customerContactId) =>
    dispatch(SET_CUSTOMER_CONTACT)
    runContactSideEffects()

I guess this more fits your first option in a way. 我想这更适合你的第一种选择。 You should probably encapsulate this complicated sequence of dispatches and side effects inside one saga, which you can kick off with a single action. 你应该把这个复杂的调度序列和副作用封装在一个传奇中,你可以用一个动作开始。 You have your complicated saga blocking on a TAKE side effect waiting for that action to be fired. 你有一个复杂的传奇阻止TAKE副作用等待该动作被触发。 Similar to what you find in this redux-saga example . 与您在此redux-saga示例中找到的内容类似。

You have a sequence like this when creating: 创建时,您有一个这样的序列:

createBooking -> chooseCustomer -> dispatch(POPULATE_BOOKING(customerId))

And this when loading 加载时这个

loadBooking -> dispatch(POPULATE_BOOKING(customerId, customerContactId))

Your complicated populateCustomerBooking saga is doing something like a takeEvery on the POPULATE_BOOKING action. 您的复杂populateCustomerBooking传奇是做一些像takeEveryPOPULATE_BOOKING行动。 This allows you to reuse all that logic, since it sounds like it should be the same. 这允许您重用所有逻辑,因为它听起来应该是相同的。 In my mind this approach is preferable because it follows DRY principles, allowing the behavior to be predictable and maintainable - you're not going to forget to update it one place and break stuff. 在我看来,这种方法更可取,因为它遵循DRY原则,允许行为可预测和可维护 - 您不会忘记将其更新到一个地方并破坏内容。 Less code to test too ;) 更少的代码来测试;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM