中继 QueryRenderer fragmentContainer 传递的道具与服务器响应不同,因为 id 冲突

Posted

技术标签:

【中文标题】中继 QueryRenderer fragmentContainer 传递的道具与服务器响应不同,因为 id 冲突【英文标题】:Relay QueryRenderer fragmentContainer passed props different from server response because id conflict 【发布时间】:2018-02-17 02:55:43 【问题描述】:

我遇到了这个奇怪的问题,基本上:

    来自QueryRenderer 的graphql 请求 从服务器返回的响应包含数据(从开发工具中的“网络”选项卡检查) props 填充在 QueryRenderer render( error, props ) 函数中 props 被传递到子组件中,createFragmentContainer 呈现值 一个字段的呈现值与响应不同

我不确定中继在从自己的存储中查找数据时在做什么,但我怀疑这是因为在类型中缺少id 声明,以下是代码示例:

App.js

<QueryRenderer
  environment=env
  query=graphql`
    query ScoreboardContainerQuery($ID: ID!) 
      scoreboard(id: $ID) 
        ...Scoreboard_scoreboard
      
    
  `
  variables=ID: gameID

  render=( error, props ) => 
    return <Scoreboard scoreboard=props ? props.scoreboard : undefined />
  
/>

Scoreboard.js

const Scoreboard = ( scoreboard ) => (
  <main>
    scoreboard.matches.map(match => <Match key=match.id match=match />)
  </main>
)

export default createFragmentContainer(Scoreboard, 
  scoreboard: graphql`
  fragment Scoreboard_scoreboard on FootballScoreboard 
    matches 
      ...Match_match
    
  
  `,
)

Match.js

const Match = ( match ) => (
  <div>
    <div>
      match.homeTeam.displayName-
      match.homeTeam.score
    </div>
    <div>
      match.awayTeam.displayName-
      match.awayTeam.score
    </div>
  </div>
)

export default createFragmentContainer(Match, 
  match: graphql`
    fragment Match_match on Match 
      date
      homeTeam  // this is a Team type
        id
        displayName
        score
      
      awayTeam  // this is a Team type
        id
        displayName
        score
      
    
  `,
)

来自服务器的matches 响应示例:

matches = [
  
    "date": "2017-09-03T06:00:00Z",
    "homeTeam": 
      "id": "330",
      "displayName": "STG",
      "score": "20"
    ,
    "awayTeam": 
      "id": "332",
      "displayName": "CBY",
      "score": "0"
    
  ,
  
    "date": "2017-08-27T06:00:00Z",
    "homeTeam": 
      "id": "329",
      "displayName": "PEN",
      "score": "14"
    ,
    "awayTeam": 
      "id": "330",
      "displayName": "STG",
      "score": "0"
    
  ,
  
    "date": "2017-08-12T05:00:00Z",
    "homeTeam": 
      "id": "330",
      "displayName": "STG",
      "score": "42"
    ,
    "awayTeam": 
      "id": "337",
      "displayName": "GCT",
      "score": "0"
    
  ,
]

渲染值:

(
  <main>
    <div>
      <div>STG-42</div>
      <div>CBY-6</div>
    </div>
    <div>
      <div>PEN-0</div>
      <div>STG-42</div>
    </div>
    <div>
      <div>STG-42</div>
      <div>GCT-18</div>
    </div>
  </main>
)

所以所有STG 值都被覆盖为42,它不应该被覆盖。

这个问题是因为Match类型中没有id响应是一个数组引起的吗? 这就是为什么中继正在寻找具有相同 ID 的 Team

【问题讨论】:

【参考方案1】:

发生这种情况是因为 Relay 每次都会更新 Team 类型的 id 330(即 SGT),并使用最新的值;最后一个是 42。

您可以从Team 中删除score 字段(这似乎有点奇怪,一个团队没有一个 得分;在一场比赛中,她有一个score),并在 Match 类型上创建 2 个字段:awayTeamScorehomeTeamScore

【讨论】:

是的,relay 需要为每种类型提供唯一 ID,因此最终为 teamID 和 matchID 创建了唯一 ID @andiwin 你是说homeTeamawayTeam 中的id 现在依赖于比赛ID,认为它是一个团队类型吗?

以上是关于中继 QueryRenderer fragmentContainer 传递的道具与服务器响应不同,因为 id 冲突的主要内容,如果未能解决你的问题,请参考以下文章

中继:在 Fragment 中使用常量而不是 graphql`...`

如何将自定义道具传递给 QueryRenderer 渲染函数?

Android中继承AppCompatActivity和直接继承Activity有啥区别呢

如何让 QueryRenderer 传播父道具更改?

GraphQL / Relay - 是不是需要在主 QueryRenderer 中查询所有表?

如何使用 Relay QueryRenderer 道具更新状态