-
Notifications
You must be signed in to change notification settings - Fork 3
/
ReasonApollo.re
89 lines (81 loc) · 2.79 KB
/
ReasonApollo.re
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module type CreationConfig = {let uri: string;};
module type ClientConfig = {type responseType; type variables;};
module Create = (CreationConfig: CreationConfig) => {
let httpLinkOptions: ApolloClient.linkOptions = {"uri": CreationConfig.uri};
let apolloClientOptions: ApolloClient.clientOptions = {
"cache": ApolloClient.inMemoryCache(),
"link": ApolloClient.httpLink(httpLinkOptions)
};
let apolloClient = ApolloClient.apolloClient(apolloClientOptions);
module Query = (ClientConfig: ClientConfig) => {
module CastApolloClient = ApolloClient.Cast({type variables = ClientConfig.variables});
let apolloClient = CastApolloClient.castClient(apolloClient);
external cast : string => {. "data": ClientConfig.responseType, "loading": bool} = "%identity";
type state =
| Loading
| Loaded(ClientConfig.responseType)
| Failed(string);
type action =
| Result(string)
| Error(string);
type retainedProps = {variables: option(ClientConfig.variables)};
let sendQuery = (~query, ~variables, ~reduce) => {
let queryConfig =
switch variables {
| Some(variables) =>
CastApolloClient.getJSQueryConfig(~query=query, ~variables=variables, ())
| None => CastApolloClient.getJSQueryConfig(~query=query, ())
};
let _ =
Js.Promise.(
resolve(apolloClient##query(queryConfig))
|> then_(
(value) => {
reduce(() => Result(value), ());
resolve()
}
)
|> catch(
(_value) => {
reduce(() => Error("an error happened"), ());
resolve()
}
)
);
};
let component = ReasonReact.reducerComponentWithRetainedProps("ReasonApollo");
let make = (~query, ~variables=?, children) => {
...component,
initialState: () => Loading,
reducer: (action, _state) =>
switch action {
| Result(result) => {
let typedResult = cast(result)##data;
ReasonReact.Update(Loaded(typedResult))
}
| Error(error) => ReasonReact.Update(Failed(error))
},
retainedProps: {variables: variables},
willReceiveProps: ({retainedProps, state, reduce}) => {
switch (variables, retainedProps.variables) {
| (Some(_variables), Some(retainedVariables)) => {
if(_variables !== retainedVariables) {
sendQuery(~query, ~variables, ~reduce);
state;
} else {
state;
}
}
| _ => state
}
},
didMount: ({reduce}) => {
sendQuery(~query, ~variables, ~reduce);
ReasonReact.NoUpdate;
},
render: ({state}) => {
children[0](state);
}
};
};
};