解释(个人备忘录)relay的todo示例(正在撰写中)
使用 `react-relay` 中的 `createFragmentContainer`、`QueryRenderer` 和 `graphql` 导入;
使用 `relay-runtime` 中的 `Environment`、`Network`、`RecordSource` 和 `Store` 导入。
解释以上的内容。 (预计需要一个小时)
1. 图灵请求语言 (GraphQL)
以下是定义GraphQL模板的方式。
尽管有一些参数和详细的使用方法,但基本上只需要定义查询。
import {graphql} from 'react-relay';
graphql`
query MyQuery {
viewer {
id
}
}
`;
2. 环境
在此定义环境变量,参数包括NetWork、RecordSource和Store。Store和NetWork是必需的。可以定义不同的环境变量,并创建两个环境。在这里进行了与GraphQL服务器通信所需的所有配置。
const {
Environment,
Network,
RecordSource,
Store,
} = require('relay-runtime');
const source = new RecordSource();
const store = new Store(source);
const network = Network.create(/*...*/); // see note below
const handlerProvider = null;
const environment = new Environment({
handlerProvider, // Can omit.
network,
store,
});
三、网络
在这里编写与graphql服务器通信的设置。将编写的网络设置传递给环境。
import {
Environment,
Network,
RecordSource,
Store,
} from 'relay-runtime';
// Define a function that fetches the results of an operation (query/mutation/etc)
// and returns its results as a Promise:
function fetchQuery(
operation,
variables,
cacheConfig,
uploadables,
) {
return fetch('/graphql', {
method: 'POST',
headers: {
// Add authentication and other headers here
'content-type': 'application/json'
},
body: JSON.stringify({
query: operation.text, // GraphQL text from input
variables,
}),
}).then(response => {
return response.json();
});
}
// Create a network layer from the fetch function
const network = Network.create(fetchQuery);
const store = new Store(new RecordSource())
const environment = new Environment({
network,
store
// ... other options
});
export default environment;
4. 查询渲染器
queryRenderer是位于relay组件树的顶部的组件。它接收query和fetch,并将结果渲染为props。类似于redux的provider的角色吧?
import React from 'react';
import { QueryRenderer, graphql } from 'react-relay';
class Example extends React.Component {
render() {
return (
<QueryRenderer
environment={environment}
query={graphql`
query ExampleQuery($pageID: ID!) {
page(id: $pageID) {
name
}
}
`}
variables={{
pageID: '110798995619330',
}}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>;
} else if (props) {
return <div>{props.page.name} is great!</div>;
}
return <div>Loading</div>;
}}
/>
);
}
}
5. 碎片容器
FragmentContainer是一个HOC。该容器并不负责获取数据。然而,通过声明嵌套渲染,它会进行渲染。
createFragmentContainer(
component: ReactComponentClass,
fragmentSpec: GraphQLTaggedNode | {[string]: GraphQLTaggedNode},
): ReactComponentClass;
假设有一个名为TodoItem的组件。该组件具有一个text属性和一个表示todo是否完成的status属性。以上的例子可能不容易理解,让我们来看一个更实际的例子。
// TodoItem.js
class TodoItem extends React.Component {
render() {
// Expects the `item` prop to have the following shape:
// {
// item: {
// text,
// isComplete
// }
// }
const item = this.props.item;
return (
<View>
<Checkbox checked={item.isComplete} />
<Text>{item.text}</Text>
</View>
);
}
}
在Relay中,使用Graphql来解决数据依赖。依赖关系将如下解决。
graphql`
# This fragment only applies to objects of type 'Todo'.
fragment TodoItem_item on Todo {
text
isComplete
}
`
import {createFragmentContainer, graphql} from 'react-relay';
class TodoItem extends React.Component {/* as above */}
// Export a *new* React component that wraps the original `<TodoItem>`.
export default createFragmentContainer(TodoItem, {
// For each of the props that depend on server data, we define a corresponding
// key in this object. Here, the component expects server data to populate the
// `item` prop, so we'll specify the fragment from above at the `item` key.
item: graphql`
fragment TodoItem_item on Todo {
text
isComplete
}
`,
});
当给定了React的组件和GraphQL时,可以使用createFragmentContainer来指定组件所需的数据。
简单来说,createFragmentContainer以组件的类名和GraphQL作为参数,创建一个具有通信功能的新容器。
(类似于Redux的connect和页面特定的saga的结合?)
export default createFragmentContainer(
TodoItem,
graphql`
fragment TodoItem_item on Todo {
text
isComplete
}
`,
);
在createFragmentContainer中,您可以通过props提取通过fetch获取的数据,如下所示。
class TodoItem extends React.Component {
render() {
const item = this.props.data;
// ...
}
}
export default createFragmentContainer(
TodoItem,
graphql`
fragment TodoItem on Todo {
text
isComplete
}
`,
);
创建RefetchContainer
创建碎片几乎相同。
创建碎片会在页面渲染时进行抓取。
但这里可以重新抓取。
当需要提前加载数据时,可以使用类似createFragments的方法来使用列表等数据。
传递商店
像是redux中的store一样的东西?好像有三种类型。
RecordSourceSelectorProxy
RecordProxy是用来改变record的接口
ConnectionHandler是用来处理关系的感觉?
数据源选择代理
RecordSourceSelectorProxy 接受哪种存储类型作为参数,其上来自以下的更新函数?
接口RecordSourceSelectorProxy {
create(dataID: string, typeName: string): RecordProxy;
delete(dataID: string): void;
get(dataID: string): ?RecordProxy;
getRoot(): RecordProxy;
getRootField(fieldName: string): ?RecordProxy;
getPluralRootField(fieldName: string): ?Array } can be paraphrased as:
RecordSourceSelectorProxy接口 {
create(dataID: string, typeName: string): RecordProxy;
delete(dataID: string): void;
get(dataID: string): ?RecordProxy;
getRoot(): RecordProxy;
getRootField(fieldName: string): ?RecordProxy;
getPluralRootField(fieldName: string): ?Array }
以下是一个示例(translation: The following is an example)
以下为对原文的中文本地化改写,只提供一个选项:
const record = store.create(dataID, ‘待办事项’);
store.delete(dataID);
const record = store.get(dataID);
const root = store.getRoot();
首先,我们来讲解一下ToDo应用的功能。接下来是App.js文件的解释。
// react-relay
QueryRenderer,
graphql, -> // react-relay
QueryRenderer,
graphql,
// relay-runtime
环境,
网络,
记录源,
存储