异步加载 mobx-state-tree 中的引用数据

Jus*_*hey 5 mobx mobx-state-tree

我查看了 mobx-state-tree 文档,甚至测试文件https://github.com/mobxjs/mobx-state-tree/blob/master/packages/mobx-state-tree/tests/core/reference- custom.test.ts#L148 找出如何从异步源填充引用节点。例如,加载了 user1 并引用了 user2,但 user2 不在树中,因此去获取 user2 并加载它。过去我让所有用户都提前加载,所以 types.late() 工作得很好。但我已停止在加载时间开始时加载所有用户,而是只想加载正在引用的用户数据。

这是一个示例片段。我实际上并没有在沙箱中运行这个示例,因为我正在向你们寻求有关在哪里以及如何异步获取丢失节点背后的逻辑的指导帮助。您会注意到,在创建商店时加载的两个用户引用了尚未加载的第三个用户。当 MST 用前两个用户填充树并遇到对已卸载用户 ID 的引用时,我们如何让它获取用户,然后将其添加到用户映射中?

export const User = types
      .model("User", {
        id: types.identifier,
        name: types.string,
        friends: types.array(types.late(types.reference(User)))
      })
      .preProcessSnapshot(snapshot => {
        if (snapshot){
            return({
              id: snapshot.id,
              name: snapshot.name,
              friends: snapshot.friends
            })
        }
      })

    export const UserStore = types
      .model("UserStore", {
        users: types.map(User),
      })
      .actions( self => ({
        fetchUser: flow(function* (userId) {
          let returnThis
          try {
            returnThis = yield ajaxFetchUser(userId) 
            self.users.put(returnThis)
          } catch (error) {
            console.log(error)
          }
          return self.users.get(returnThis.id)
        })
      }))

    UserStore.create({
      users:[{
        id: 1,
        name: "Justin",
        friends: ["2","3"]
      },{
        id: 2,
        name: "Jack",
        friends: ["1","3"]
      }]
    })

    const ajaxFetchUser = (userId) => {
      // pretend that userId is 3
      setTimeout(()=>{
        return {
          id:3,
          name: "John",
          friends: ["1","2"]
        }
      }, 3000)
    }
Run Code Online (Sandbox Code Playgroud)

当然,我使用的脚本比此代码复杂得多,具有适当的 map.put 和 map.get 操作。

如果有人能对这个问题有所启发,我将非常感激。

jay*_*rjo 1

您可以尝试通过将其转换为 getter(基本上是创建视图)来拦截尝试访问特定属性(在您的案例参考中)的人,并从那里安排一个操作(数据获取)。我知道你似乎在那里违反了某些规定(确实如此),但这就是你所追求的。我认为这就是 MobX 的幕后运作方式,也许它违反了最佳实践这一事实促使其作者转而使用代理。嗯...您可能也想尝试代理