首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >响应中继createFragmentContainer和QueryRenderer数据流

响应中继createFragmentContainer和QueryRenderer数据流
EN

Stack Overflow用户
提问于 2020-05-07 08:41:16
回答 1查看 673关注 0票数 0

我一直在研究QueryRenderer https://relay.dev/docs/en/query-renderer和FragmentContainer https://relay.dev/docs/en/fragment-container的中继文档中的示例

对于如何让封装在特殊createFragmentContainer中的组件访问数据,我感到困惑。

我有一个顶级的QueryRenderer:

代码语言:javascript
复制
function renderFunction({error, props}) {
...
  if (props) {
    // Added todoList as a prop with a distinct name from tdlist which
    // is meant to be passed in by createFragmentContainer
    return <TodoList todoList = {props.todoList} />
  }
...
}
export default function ContainerWithQueryRenderer() {
  return (
    <QueryRenderer
      environment={environment}
      query={graphql`
        query ContainerWithQueryRenderer_Query {
          todoList {
            title
            todoListItems { text isComplete}
          }
        }`}
      render = { renderFunction }
    />
  );
}

和一个TodoList组件,它定义了graphql片段中需要哪些数据:

代码语言:javascript
复制
import React from 'react';
import TodoItem from './TodoItem.js';
import { createFragmentContainer } from 'react-relay';
import graphql from 'babel-plugin-relay/macro';
function TodoList(props) {
  console.log('TodoList props:',props);
  if (props && props.todoList && props.todoList.todoListItems && props.todoList.title) {
    return (
      <div className='list-container'>
        <div className='list-header'>
          <div className='list-header-label'>{props.todoList.title}</div>
        </div>
        <div className='list'>{props.todoList.todoListItems.map( (item, key) => <TodoItem key = {key} item={item} />)}</div>
      </div>
    );
  } else {
    return null;
  }
}
export default createFragmentContainer(TodoList,{
  tdlist: graphql`
    fragment TodoList_tdlist on TodoList {
      title
      todoListItems {
        ...TodoItem_item
      }
    }
  `,
})

还有一个孩子TodoListItem

代码语言:javascript
复制
import React from 'react';
import { createFragmentContainer } from 'react-relay';
import graphql from 'babel-plugin-relay/macro';
function TodoItem(props) {

  return <div className='list-item'>
      <div className='list-item-label'>{props.item.text}</div>
      {props.item.isComplete ?<div className='list-item-buttons'>Done</div>:null}
    </div>
}

export default createFragmentContainer( TodoItem,{
  item: graphql`
    fragment TodoItem_item on Todo {
      text isComplete
    }
  `
});

我的理解是,用于createFragmentContainer的TodoList将将来自TodoList_tdlist片段的数据注入为TodoList props.tdlist),形状按graphql查询的形状而定。

然而,这种情况似乎没有发生。我在控制台收到警告:

Warning: createFragmentSpecResolver: Expected prop `tdlist` to be supplied to `Relay(TodoList)`, but got `undefined`. Pass an explicit `null` if this is intentional.

如果createFragmentContainer不传递tdlist,那么它的工作是什么?

我试图显式地传递todoList数据,方法是将返回更改为返回( createFragmentContainer传入的相同的道具名称),我(可以理解)得到了另一个错误:

代码语言:javascript
复制
Warning: RelayModernSelector: Expected object to contain data for fragment `TodoList_tdlist`, got `{"title":"Your to-do list","todoListItems":[{"text":"Brush teeth","isComplete":false},....

我认为我困惑的根源在于不理解定义数据依赖项的片段如何与QueryRenderer交互。我是否需要定义查询以获取可能需要的所有可能的数据,重点是中继只会通过查看当前呈现的组件的graphql片段来查询所需的内容,并将重新查询如果发生变化,在获得新数据时更新支持?

我是否需要将道具显式地传递到片段容器,或者如果它们是请求其数据的QueryRenderer的后代,那么createFragmentContainer是否能够通过中继环境访问它?

下面是我的graphql.schema来帮助您:

代码语言:javascript
复制
type Query {
  todoList: TodoList!
}
type Todo {
  text: String!
  isComplete: Boolean!
}
type TodoList {
  title: String!
  todoListItems: [Todo]!
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-07 23:52:05

您必须在您的GraphQL中命名子代片段容器的QueryRenderer片段。在没有识别片段的情况下,react继电器在QueryRenderer和后代FragmentContainer组件之间没有中继。在您的问题中,传递给query的QueryRenderer支柱是

query ContainerWithQueryRenderer_Query { todoList { title todoListItems { text isComplete }}}

而不是

query ContainerWithQueryRenderer_Query { TodoList_tdlist }

另外,由于QueryRenderer与片段容器协同工作,所以在QueryRenderer中迭代todoListItems并为TodoItem_item使用一个片段更为简单。因此,下面我合并了上面的<ContainerWithQueryRenderer /><TodoList />

这一办法行之有效:

TodoListWithQueryRenderer.js:

代码语言:javascript
复制
function renderFunction({error, props}) {
...
  if (props) {
    return (
        <div>
          <div>
            <div>{props.todoList.title}</div>
          </div>
          <div>{props.todoList.todoListItems.map( (item, key) => <TodoItem key = {key} item={item} /> )}</div>
        </div>
      );
  }
...
}
export default function TodoListWithQueryRenderer() {
  return (
    <QueryRenderer
      environment={environment}
      query={graphql`
        query TodoListWithQueryRenderer_Query { todoList {todoListItems {...TodoItem_item } title} }
      `}
      render = { renderFunction }
    />
  );
}

上面只需要一个子代组件,将ContainterWithQueryRenderer与TodoList组件合并。

TodoItem.js:

代码语言:javascript
复制
import React from 'react';
import { createFragmentContainer } from 'react-relay';
import graphql from 'babel-plugin-relay/macro';
function TodoItem(props) {

  return <div>
      <div>{props.item.text}</div>
      {props.item.isComplete ? <div>Done</div> : null}
    </div>
}

export default createFragmentContainer( TodoItem,{
  item: graphql`
    fragment TodoItem_item on Todo {
      text isComplete
    }
  `
});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61653457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档