Reputation: 58
I'm having issue of displaying the response of the API. It appears white like this
Which is should be similar like this
My code in the backend server:
main.ts
import { typeDefs, resolvers } from './src/graphql/Resolver'
AppDataSource.initialize()
const app = express()
const httpServer = http.createServer(app)
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })]
});
(async () => {
await server.start()
app.use(
'/gql',
cors<cors.CorsRequest>({ origin: `http://${process.env.DOMAIN}:${process.env.CLIENT_PORT}`, credentials: true }),
express.json(),
cp(),
expressMiddleware(server, {
context: async ({ req, res }) => ({ req, res })
})
)
httpServer.listen(process.env.PORT)
})()
Resolver.ts
import API from './resolver/api/Data'
import Books from './resolver/api/Books'
export const typeDefs = Schema
export const resolvers = {
API: {
__resolveType(obj: API) {
if ((obj as Data).user_id) return 'Data'
else return 'Error'
}
},
Data: {
books: Books
},
Query: {
api: API
}
}
Data.ts
const Data = async (_: null, args: { api_key: string }) => {
try {
const userRepo = AppDataSource.getRepository(User)
const { api_key } = args
const hashBuffer = Buffer.from(api_key, 'hex')
const user = await userRepo.findOne({ where: { api_key: hashBuffer } })
if (!user) return { message: 'Invalid API Key!'}
return {
user_id: user.user_id,
email: user.email,
username: user.username
}
} catch {
throw new GraphQLError('Internal Server Error', { extensions: { code: '500' } })
}
}
export default Data
Books.ts (the parent refers to Data
)
const Books = async (parent: { user_id: number }) => {
try {
const bookRepo = AppDataSource.getRepository(Book)
const books = await bookRepo.find({ where: { user_id: parent!.user_id } })
return books.map(book => ({
cover_i: book.cover_i,
isbn: book.isbn,
title: book.title,
author_name: book.author_name
}))
} catch {
throw new GraphQLError('Internal Server Error', { extensions: { code: '500' } })
}
}
export default Books
Frontend:
App.tsx
const App: React.FC = () => {
const { loading, data, error } = useQuery(AuthGQL)
const dispatch = useDispatch()
React.useEffect(() => {
if (!loading) {
if (data) dispatch(setUser(data.auth))
else if (error) dispatch(setUser(null))
}
}, [data, error])
return (
<BrowserRouter>
<main>
<Routes>
<Route path="API/:hash" element={<API />} />
</Routes>
</main>
</BrowserRouter>
)
}
export default App
API.tsx
interface Book {
cover_i: string
isbn: string
title: string
author_name: string
__typename: string
}
const API: React.FC = () => {
const { hash } = useParams<{ hash: string }>()
const { loading, data, error } = useQuery(APIGQL, { variables: { api_key: hash } })
const apiState = useSelector((state: RootState) => state.API)
const dispatch = useDispatch()
React.useEffect(() => {
if (!loading) {
if (data) {
const { __typename, books, ...api } = data.api
dispatch(setApi({
...api,
books: books.map(({ __typename, ...book }: Book) => book)
}))
}
else if (error) { }
}
}, [data, error])
return (
<pre>{JSON.stringify(apiState, null, 2)}</pre>
)
}
export default API
I have no idea how to displaying like that. Asking GPT forces me to use CSS style while I'm pretty sure the Open Library API doesn't use that way.
Upvotes: 0
Views: 38
Reputation: 113
You can't do that with GQL
since GQL
need a POST
request. It can't return json
like that. But you can combine REST
with your GQL
.
main.ts
(async () => {
await server.start()
app.use(
'/gql',
cors<cors.CorsRequest>({ origin: `http://${process.env.DOMAIN}:${process.env.CLIENT_PORT}`, credentials: true }),
express.json(),
cp(),
expressMiddleware(server, {
context: async ({ req, res }) => ({ req, res })
})
)
// since I saw your format URL is somewhat '/API/hash'
app.get('/API/:hash', async (req: Request, res: Response) => {
try {
const userRepo = AppDataSource.getRepository(User)
const { hash } = req.params
const hashBuffer = Buffer.from(hash, 'hex')
const user = await userRepo.findOne({ where: { api_key: hashBuffer } })
if (!user) res.status(404).json({ message: 'Invalid API Key!' })
// continue the logic
res.status(200).json(JSON.parse(JSON.stringify('return your dict response', null, 2)))
} catch {
}
}
httpServer.listen(process.env.PORT)
})()
Upvotes: 1
Reputation: 3019
Open Library API returns raw json, which is displayed in the default font and background of your browser, usually black font over white background except when using something like a dark theme. If you want to control the display you will have to use CSS and or rendering markup for your json.
The simplest way here is to style the element you're stringifying your json into:
return (
<pre style={{ color: 'white'; background: 'black' }}>
{JSON.stringify(apiState, null, 2)}
</pre>
);
If you do not want to control the display instead of querying the API in a React component, just navigate to your API endpoint.
look into useNavigate if your API accepts searchParams, otherwise you probably will need a form element
Upvotes: 1