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.
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.
Share Improve this question asked Feb 3 at 17:22 VireZeeVireZee 585 bronze badges 4- 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 – remix23 Commented Feb 3 at 17:32
- so how do I make return raw json like that, since in the white theres no check mark button like pretty-print. I want to make the same way like open library – VireZee Commented Feb 3 at 17:34
- I'm using same browser and pc. but get different result – VireZee Commented Feb 3 at 17:37
- Your API also returns raw json, but you're using react to display it in a web page, which can be styled. So your API is fine but if you want to display it's result in a styled way you can have a look at my answer. – remix23 Commented Feb 3 at 17:42
2 Answers
Reset to default 1You 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)
})()
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