ReactRouterV7 with @graphql-codegen/typescript-react-apollo yields error: __vite_ssr_import_3__.useQuery is not a function
Which packages are impacted by your issue?
@graphql-codegen/typescript-react-apollo
Describe the bug
Issue
- In a ReactRouter V7 (as a framework) with vite and apollo:
- Once query hooks have been generated with @graphql-codegen/typescript-react-apollo
- the import of Apollo inside the generated file breaks the app with this error:
TypeError: __vite_ssr_import_[importNb]__.useQuery is not a function
Your Example Website or App
https://stackblitz.com/edit/github-kocgurap-ascqncjf
Steps to Reproduce the Bug or Issue
- on the reproduction, run
npm install && npm run dev
- the app fails with error "vite_ssr_import_2.useQuery is not a function"
Expected behavior
The npx create-react-router@latest app should run.
Screenshots or Videos
Platform
- OS: macOS
- NodeJS: tested on v18.20.3 && v20.16.0
graphqlversion: "graphql": "^16.10.0", "graphql-tag": "^2.12.6",@graphql-codegen/*version(s): "@graphql-codegen/cli": "^5.0.4", "@graphql-codegen/near-operation-file-preset": "^3.0.0", "@graphql-codegen/typescript": "^4.1.3", "@graphql-codegen/typescript-operations": "^4.4.1", "@graphql-codegen/typescript-react-apollo": "^4.3.2",
Codegen Config File
import { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = { schema: 'schema.graphql', documents: 'document.graphql', config: { gqlImport: 'graphql-tag#gql', }, generates: { 'types.ts': { plugins: [ 'typescript', 'typescript-operations', 'typescript-react-apollo', ], }, }, };
export default config;
Additional context
I thought the solution would be to import like this:
import Apollo from '@apollo/client';
instead of the current:
import * as Apollo from '@apollo/client';
but it doesn't seem to work either ('@apollo/client/index has no default export')
Failing test / Solution:
I've looked into this, but I don't know how to solve this
Unrelated issue:
I couldn't use the CodeSandbox link to create a reproduciton repo:
I have no idea how to fix this issue inside the lib, but I fixed it in my project by running the following script once I've generated my files:
/* eslint-disable no-console */
import * as fs from 'fs';
import * as path from 'path';
const generatedFilesDir = './app/gql';
fs.readdir(generatedFilesDir, (err, files) => {
if (err) {
console.error('Error reading directory:', err);
return;
}
files.forEach((file) => {
if (file.endsWith('.generated.ts')) {
const filePath = path.join(generatedFilesDir, file);
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
// Remove the old import statement
const dataWithoutOldImport = data.replace(
/import \* as Apollo from '@apollo\/client';\s*/g,
''
);
// Find all Apollo.xxx and collect unique xxx
const apolloRegex = /Apollo\.(\w+)/g;
let match;
const apolloMethods = new Set<string>();
while ((match = apolloRegex.exec(dataWithoutOldImport)) !== null) {
apolloMethods.add(match[1]);
}
// Create import statements for each unique xxx
const importStatements = Array.from(apolloMethods)
.map((method) => {
if (/^[A-Z]/.test(method)) {
return `import type { ${method} } from '@apollo/client/index.js';`;
} else {
return `import { ${method} } from '@apollo/client/index.js';`;
}
})
.join('\n');
// Replace Apollo.xxx with xxx
const updatedData = dataWithoutOldImport.replace(apolloRegex, (match, p1) => p1);
// Insert import statements at the top of the file
const finalData = importStatements + '\n' + updatedData;
fs.writeFile(filePath, finalData, 'utf8', (err) => {
if (err) {
console.error('Error writing file:', err);
} else {
console.log(`Updated file: ${filePath}`);
}
});
});
}
});
});