Javascript 使用mobx实现延迟加载的惯用方法

Javascript 使用mobx实现延迟加载的惯用方法,javascript,reactjs,lazy-loading,mobx,Javascript,Reactjs,Lazy Loading,Mobx,当使用MobX时,当前惰性加载属性的惯用方法是什么 我已经为此挣扎了几天,自从严格模式成为一种东西以来,我还没有找到任何好的例子。我喜欢严格模式的想法,但我开始认为延迟加载与之不符(如果数据不存在,访问或观察属性会触发加载数据的副作用) 这是我问题的症结所在,但为了了解我是如何来到这里的,请继续阅读 我当前设置的基本内容(无需发布大量代码): 反应组件1(列表视图): 组件将安装 componentWillMount&componentWillReceiveProps-该组件从路由参数(reac

当使用MobX时,当前惰性加载属性的惯用方法是什么

我已经为此挣扎了几天,自从严格模式成为一种东西以来,我还没有找到任何好的例子。我喜欢严格模式的想法,但我开始认为延迟加载与之不符(如果数据不存在,访问或观察属性会触发加载数据的副作用)

这是我问题的症结所在,但为了了解我是如何来到这里的,请继续阅读

我当前设置的基本内容(无需发布大量代码):

反应组件1(列表视图): 组件将安装

  • componentWillMount&componentWillReceiveProps-该组件从路由参数(react router)获取筛选器值,将其保存为ListView上的可观察对象,并告知存储区根据该值获取“建议”
  • Store.fetchPropositions检查是否已发出该请求(请求存储在ObservableMap中,通过序列化筛选器对象来设置键,以便两个相同的筛选器将返回相同的响应对象)。如果需要,它会发出请求,并返回可观察的响应对象,该对象包含关于请求是否已完成或是否存在错误的信息。
  • ListView将可观察响应对象保存为属性,以便它可以显示加载或错误指示器
  • ListView有一个计算属性,该属性使用用于获取的相同筛选器对象调用Store.getPropositions
  • Store.GetPropositions是一个转换器,它接受筛选器对象,从ObservableMap(keys on Proposition.id)获取所有建议,使用筛选器对象筛选列表并返回建议[](如果没有与筛选器匹配的内容,则为空,包括尚未加载任何建议)
  • 这一切似乎都很有效

    问题在于提案具有客户端和客户端ID的属性。Proposition.clientId是一个与Proposition一起加载的字符串。我想等到客户机被实际访问后,再告诉存储从服务器获取它(假设它不在存储中)。在本例中,ListView恰好显示客户机名称,因此应在提交建议后不久加载该名称

    我得到的最接近的结果是在提案的构造函数列表中设置自动运行,但其中的一部分并不是在我确定的地方做出反应。(截至相关章节):

    @observable private clientId:string='';
    @可观察的私有clientFilter:IClientFilter=null;
    @可观察客户机:客户机=空;
    构造函数(sourceJson?:any){
    super(sourceJson);
    if(sourceJson){
    this.mapFromJson(sourceJson);
    }
    //这一个有效。我正在将clientId字符串转换为getClients转换器的对象
    自动运行(()=>{runInAction(()=>{this.clientFilter={id:this.clientId};})});
    自动运行(()=>{
    运行不活动(()=>{
    if(this.clientId&&this.clientFilter){
    const clients=DataStore.getClients(this.clientFilter);
    const response=DataStore.fetchClients(this.clientFilter);
    if(response.finishedTime!==null&&!response.hasErrors){
    this.client=clients[0]| | null;
    console.log('从未调用过它,但我应该在这里看到一个客户端:%o',DataStore.getClients(This.clientFilter));
    }
    }
    })
    });
    }
    
    响应对象是可观察的:

    这是工作

    我想我需要其中的自动运行来根据这个objects clientId/clientFilter属性进行更新(如果这个对象后来被分配给一个新的客户端,我希望lazyObservable被更新)。我不介意为懒散的属性提供一个小样板,但我绝对愿意接受那里的建议


    如果这最终成为了解决方法,我也将从同一个lib而不是我的可观察请求对象中查看。不确定,因为我正在跟踪开始时间以检查是否过时。在这里链接,以防其他人没有遇到:)

    我在项目中使用了不同的方法,并将其提取到一个单独的npm包中:

    下面是一个简单的例子:

    首先,我们需要一个React组件来显示客户端信息:

    @observer
    class ClientView extends React.Component {
      render() {
        const entry = clientCache.get(this.props.clientId)
    
        if (entry.status !== 'success') {
          // Return some kind of loading indicator here.
          return <div>Still loading client...</div>
        }
    
        const clientInfo = entry.value
        // Now you can render your UI based on clientInfo.
        return (
          <div>
            <h2>{clientInfo.name}</h2>
          </div>
        )
      }
    }
    

    这就是你需要做的。MobxCache将在需要时自动调用
    fetchClient(id)
    ,并为您缓存数据。

    如果需要,我很乐意发布更多代码,只是尝试缩短文本墙。为什么所有内容都以
    @Mobx作为前缀。
    您不能进行解构导入吗?您可以在存储层缓存数据,在promise中,或者在MobX中有一个Repository类来处理与服务器的接触。总的来说,我发现自动运行表明代码存在更深层次的问题。@BenjaminGruenbaum-这就是我们正在使用的样式,所以很明显,它来自Mobx。本打算在评论中删除,但忘记了:/@BenjaminGruenbaum-(呵呵,刚才注意到两条评论都是你:)我一拿到数据就在商店里缓存数据。我试着沿着承诺的道路走了一段时间,但没有任何运气。你不会碰巧知道有这样一个项目,我可以把它作为一个例子来看待?我同意自动运行指示问题,我正试图找出一种更好的方法来构建所有这些。谢谢谢谢@Jakke!该图书馆仍处于早期开发阶段,如有任何反馈,我将不胜感激:)有趣。但糟糕的是,在
    render()
    中启动的fetch打破了习惯用法,并没有任何副作用
    render()
    client = lazyObservable((sink) => {
        autorun('lazy fetching client', () => {
            if (this.clientFilter && this.clientFilter.id) {
                const request = DataStore.fetchClients(this.clientFilter);
                if (request.finishedTime !== null && !request.hasErrors) {
                    sink(request.items[0]);
                }
            }
        })
    }, null);
    
    @observer
    class ClientView extends React.Component {
      render() {
        const entry = clientCache.get(this.props.clientId)
    
        if (entry.status !== 'success') {
          // Return some kind of loading indicator here.
          return <div>Still loading client...</div>
        }
    
        const clientInfo = entry.value
        // Now you can render your UI based on clientInfo.
        return (
          <div>
            <h2>{clientInfo.name}</h2>
          </div>
        )
      }
    }
    
    import MobxCache from "mobx-cache";
    
    function fetchClient(id) {
      // Use any fetching mechanism you like. Just make sure to return a promise.
    }
    
    const clientCache = new MobxCache(fetchClient)