relayのtodo exampleを解説（超個人的メモ）（執筆途中）

![alt](https://user-images.githubusercontent.com/26253721/39765058-e8d0eae4-531b-11e8-9305-4c852f269517.png)
relayのtodo　exampleを見てみた。
以下が、importされていた。ということは以下の要素を読み解けばrelayが何かわかるはずだ。

import {
  createFragmentContainer,
  QueryRenderer,
  graphql,
} from 'react-relay';
import {
  Environment,
  Network,
  RecordSource,
  Store,
} from 'relay-runtime';

以上のものを解説していく。 (一時間を予定)

# 1.graphql
以下のようにgraphqlのテンプレートを定義する。
引数など、細かな使い方はあるが、基本的にはクエリを定義するだけ。

```js
import {graphql} from 'react-relay';

graphql`
  query MyQuery {
    viewer {
      id
    }
  }
`;
```

# 2.Environment 
環境変数を定義する。　引数は　NetWork, RecordSource, Store
storeとnetworkは必須。別々の環境変数を定義して、二つのEnvironmentを作成することも可能。
graphqlサーバーと通信するための設定を全てここで行う。

```js
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,
});
```

# 3.Network
graphqlサーバと通信するための設定をここに書く。書いたNetWorkはEnvironmentに食わせる

```js
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
queryRendererはrelayコンポーネントツリーの頂上にあるコンポーネントです。
queryとfetchを受け取り、結果をpropsとしてレンダリングします。
reduxのproviderのような役割のものかな？

```js
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
FragmentContainerはHOCです。このcontainerはdataをfetchするわけではありません。しかし、ネストされたレンダリングを宣言することでレンダリングします。

```js
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を使って解決します。依存は以下のように解決されます。

```js
graphql`
  # This fragment only applies to objects of type 'Todo'.
  fragment TodoItem_item on Todo {
    text
    isComplete
  }
`
```

```js
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のcomponentとgraphqlが与えられた時、createFragmentContainerでcomponentが要求するデータを指定できます。
要するにcreateFragmentContainerはcomponentのclass名とgraphqlを引数にとり、通信機能をもつ新しい
containerを作ります。（reduxのconnectとページ固有のsagaが一緒になった感じ？）

```
export default createFragmentContainer(
  TodoItem,
  graphql`
    fragment TodoItem_item on Todo {
      text
      isComplete
    }
  `,
);
```
createFragmentContainerの中でfetchしたデータは以下のようにpropsで取り出せます。

```js
class TodoItem extends React.Component {
  render() {
    const item = this.props.data;
    // ...
  }
}

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

# createRefetchContainer
createFragmentsとほぼ同じ。
createFragmentsはページがレンダリングされるときにfetchする。
ただこちらはrefetchができる。
# 
createFragmentsとほぼ同じ
リストなどで、データを先に読み込んでおきたい時に使う。

# Relay Store
reduxのstoreのようなもの？　なんか３種類あるみたい。
RecordSourceSelectorProxy
RecordProxy recordをmutateするインターフェース
ConnectionHandler　relationを扱う感じ？

## RecordSourceSelectorProxy
RecordSourceSelectorProxyは以下のupdater functionを引数にとるstoreのタイプ?

interface 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<?RecordProxy>;
}

以下は例

const record = store.create(dataID, 'Todo');
store.delete(dataID);
const record = store.get(dataID);
const root = store.getRoot();

それではtodoアプリの解説を書いていく。
まず、App.js

// react-relay
  QueryRenderer,
  graphql,

// relay-runtime
  Environment,
  Network,
  RecordSource,
  Store,