Download this project, goto example/server, execute
yarn install
yarn start
Choose any another dir, execute
yarn create react-app <YourAppName> --template typescript
Goto the root dir of your app, execute
yarn add \
react-relay @types/react-relay \
relay-runtime @types/relay-runtime \
graphql-ts-client-api \
graphql-ts-client-relay
yarn add graphql-ts-client-codegen --dev
Notes:
1. relay-compiler & babel-plugin-relay are unnecessary, don't add them. Be different with relay-compiler, generating code by graphql-ts-client-codegen is one-time work!
2. My npm libraries are 'graphql-ts-client-api', 'graphql-ts-client-codegen' and 'graphql-ts-client-relay'. There is another library named 'graphql-ts-client' in npm repository, but that's not my framework.
Goto the root dir or your app
mkdir scripts
cd scripts
touch GraphQLCodeGenerator.js
Open the new file and paste code
const {RelayGenerator, loadRemoteSchema} = require("graphql-ts-client-codegen");
const path = require("path");
const generator = new RelayGenerator({
schemaLoader: async() => {
return loadRemoteSchema("http://localhost:8080/graphql");
},
targetDir: path.join(__dirname, "../src/__generated"),
defaultFetcherExcludeMap: {
"Department": ["avgSalary"]
},
});
generator.generate();
Notes
defaultFetcherExcludeMap: { "Department": ["avgSalary"] }
Can only work with the server of the attached demo of this framework, if you are generating code for other servers, please delete it.
Open the package.json of the root dir, find the object "scripts" and add this field into it
"codegen": "node scripts/GraphQLCodeGenerator.js"
Goto the root dir of your app, execute
yarn codegen
Notes:
This is a one-time job! Be different relay-compiler, you need not to generate code again and again.
After this step, you can forget the code generator until the server-side team tell you their interface has been changed.
Change 'src/App.tsx' of your app, copy & paste this code
import { FC, memo, Suspense } from 'react';
import { RelayEnvironmentProvider } from 'react-relay';
import { Environment, Network, RecordSource, RequestParameters, Store, Variables } from 'relay-runtime';
import './App.css';
import { createTypedQuery, loadTypedQuery, PreloadedQueryOf, useTypedPreloadedQuery } from './__generated';
import { department$$, employee$, employeeConnection$, employeeEdge$, query$ } from './__generated/fetchers';
export const environment = new Environment({
network: Network.create(async (params: RequestParameters, variables: Variables) => {
console.log(`fetching query ${params.name} with ${JSON.stringify(variables)}`);
const response = await fetch('http://localhost:8080/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: params.text,
variables,
}),
});
return await response.json()
}),
store: new Store(new RecordSource()),
});
function App() {
return (
<RelayEnvironmentProvider environment={environment}>
<Suspense fallback="Loading...">
<Example queryReference={queryReference}/>
</Suspense>
</RelayEnvironmentProvider>
);
}
const EMPLOYEE_LIST_QUERY = createTypedQuery(
"EmployeeListQuery",
query$
.findEmployees(
employeeConnection$.edges(
employeeEdge$.node(
employee$.id.firstName.lastName
.department(
department$.id.name
)
.supervisor(
employee$.id.firstName.lastName
)
.subordinates(
employee$.id.firstName.lastName
)
)
)
)
)
const queryReference = loadTypedQuery(
environment,
EMPLOYEE_LIST_QUERY,
{}
);
const Example: FC<{
queryReference: PreloadedQueryOf<typeof EMPLOYEE_LIST_QUERY>
}> = memo(({queryReference}) => {
const data = useTypedPreloadedQuery(EMPLOYEE_LIST_QUERY, queryReference);
return (
<>
{
data?.findEmployees.edges.map(edge => {
const employee = edge.node;
return (
<div key={employee.id} style={{border: "solid 1px gray", margin: "1rem"}}>
<div>Name: {employee.firstName} {employee.lastName}</div>
<div>Department: { employee.department.name} </div>
<div>
Supervisor:
{
employee.supervisor !== undefined ?
`${employee.supervisor.firstName} ${employee.supervisor.lastName}` :
<span style={{fontStyle: "italic", color: "gray"}}>No supervisor</span>
}
</div>
<div>
Suborinates:
{
employee.subordinates.length !== 0 ?
<ul style={{margin: 0}}>
{employee.subordinates.map(subordinate =>
<li key={subordinate.id}>{subordinate.firstName} {subordinate.lastName}</li>
)}
</ul> :
<span style={{fontStyle: "italic", color: "gray"}}>No subordinates</span>
}
</div>
</div>
);
})
}
</>
);
});
export default App;
Goto the root dir of your app, execute
yarn start
This is the simplest demo, you can view the full demo relay-tutorial to know more