使用 RelayRouter 导航 relay.js 应用程序抛出 Invalid State Change 错误

Posted

技术标签:

【中文标题】使用 RelayRouter 导航 relay.js 应用程序抛出 Invalid State Change 错误【英文标题】:Navigating relay.js app with RelayRouter throwing Invalid State Change error 【发布时间】:2016-06-16 10:27:39 【问题描述】:

我正在编写一个 relay.js 应用程序,并且我正在使用 react-relay-router 进行路由。路由有效,但我相信它暴露了我对如何跨不同视图组织查询片段的误解。

app.js中定义的路由

const rootComponent =
  (<RelayRouter history=hashHistory>
    <Route path="/"
      component=App
      queries=ViewerQueries
      onReadyStateChange=this.handleStateChange
    >
      <IndexRoute
        component=Dashboard
        queries=ViewerQueries
      />
      <Route
        path="/org_setup"
        component=OrgSetup
        queries=ViewerQueries
      />
      <Route
        path="/admin/data_models"
        component=DataModelList
        queries=ViewerQueries
      />
    </Route>
  </RelayRouter>);
ReactDOM.render(rootComponent, mountNode);

DataModelList.js中的查询片段声明

export default Relay.createContainer(DataModelList, 
  fragments: 
    viewer: () => Relay.QL`
      fragment on User 
        dataModels(first: 10) 
          edges 
            node 
              id,
              name,
              isAuthority,
              categories(first: 10) 
                edges 
                  node 
                    id,
                    name,
                    tags(first: 10) 
                      edges 
                        node 
                          id,
                          code,
                          label,
                        
                      
                    
                  
                
              ,
              adapter 
                categories(first: 10) 
                  edges 
                    node 
                      id,
                      name,
                    
                  
                
              
            
          
        ,
      
    `,
  ,
);

OrgSetup.js中的查询片段

export default Relay.createContainer(OrgSetup, 
  fragments: 
    viewer: () => Relay.QL`
      fragment on User 
        dataModels(first: 10) 
          edges 
            node 
              id,
              name,
              isAuthority,
              categories(first: 10) 
                edges 
                  node 
                    id,
                    name,
                    tags(first: 10) 
                      edges 
                        node 
                          id,
                          code,
                          label,
                        
                      
                    
                  
                
              ,
            
          
        ,
      
    `,
  ,
);

DataModelListOrgSetup 之间导航(在任一方向)时,我在控制台中看到以下错误:

Server request for query `ViewerQueries` failed for the following reasons:

1. Cannot query field "node" on "Query".
   rQueries($id_0:ID!)node(id:$id_0)id,__typename,...F0 fra

Warning: RelayReadyState: Invalid state change from 
"aborted":false,"done":false,"error":"source":"data":null,"errors":
["message":"Cannot query field \"node\" on \"Query\".","locations":
["line":1,"column":32]],"ready":false,"stale":false` to `"error":
"source":"data":null,"errors":["message":"Cannot query field \"node\" on 
\"Query\".","locations":["line":1,"column":32]]`.warning @ 
app.js:31567update @ app.js:39409onRejected @ app.js:39035tryCallOne @ 
app.js:30045(anonymous function) @ app.js:30131flush @ app.js:30279

我可以通过使两个视图中的查询片段相同来防止发生此错误 - 特别是通过添加 adapter 片段。

但是,这感觉不对。它们不需要完全相同(事实上,它们现在有些臃肿,因为这对我来说是一个学习应用程序),其他视图当然不会共享这些数据需求。

    保持查询声明简洁的最佳做法是什么? 理想情况下,我会让***视图只声明***数据 要求。具体来说,在我的示例视图文件中,我会要求 只有viewer 和他们的dataModels,然后允许孩子 组件来表达他们的需求,请求任何嵌套数据(例如 categoriestagsadapters 以及它们各自的 categories)。 invalid state change 错误的真正含义是什么?我可以看到 它对完全匹配的查询感到满意,但我不能 想象一下共享查询声明需要不相关的视图。一世 怀疑这是我在其他地方做错事的副产品。

谢谢!

【问题讨论】:

关于 invalid state change 错误:看起来第二个状态更改正在被刷新而没有适当的状态更改属性(中止、完成等)。我想知道那些是从哪里来的。如果您有时间在 Relay Playground 上制作重现案例,我们很乐意提出问题或拉取请求。 github.com/facebook/relay/blob/master/src/store/… @steveluscher 这个错误现在已经消失了,因为我有 1) 在 nodeInterface 中包含解析 adapter 的逻辑和 2) 在根查询上设置 node 字段。谢谢! 【参考方案1】:

当查询更改时(例如,由于路由转换或对setVariables() 的调用),中继将区分您来自的查询和您要去的查询,计算最小查询以获取您从 A 到 B。在您的情况下,Relay 从存储在客户端上的一系列已知记录(已获取的记录)开始,并尝试仅获取这些确切记录上的新字段,以构建完整的世界。这些重新获取依赖于称为 node interface 的东西。

符合中继的 GraphQL 服务器必须公开一个名为 node 的根字段,该字段可以获取给定全局 ID 的任何记录。此字段必须采用 GraphQLID! 类型的 id 参数。

有关如何构建此类根字段的示例,请参阅this graphql-js example。

【讨论】:

感谢您的明确解释。这正是我做错的。我已经定义了一个节点接口,但愚蠢地忘记了通过根 node 字段将它连接到我的查询。

以上是关于使用 RelayRouter 导航 relay.js 应用程序抛出 Invalid State Change 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何同时使用导航抽屉和底部导航 - 导航架构组件

如何一起使用底部导航栏和侧边导航栏,我的侧边导航按钮不显示,而是底部导航

高德导航怎么用 怎样使用高德地图进行导航

使用片段导航(导航图)导航时调用目标片段的函数/方法

使用底部导航栏导航回页面时颤动通过底部导航栏选择的索引

百度地图离线导航要怎样使用?