Skip to content

Instantly share code, notes, and snippets.

@zaydek
Created March 12, 2020 09:07
Show Gist options
  • Save zaydek/f80406342d8bb5951ab83c3435106d7b to your computer and use it in GitHub Desktop.
Save zaydek/f80406342d8bb5951ab83c3435106d7b to your computer and use it in GitHub Desktop.
import React, { Component } from "react";
import { CatServiceClient } from "../../proto/api/v1/ApiServiceClientPb";
import {
GetFeaturedCatsRequest,
Cat,
GetFeaturedCatsResponse
} from "../../proto/api/v1/api_pb";
import {
Icon,
Text,
Box,
Image,
Heading,
Grid,
CircularProgress,
Alert,
AlertIcon,
AlertDescription,
AlertTitle
} from "@chakra-ui/core";
import { Error, Status } from "grpc-web";
// interface FeaturedCatsProps {
// client: CatServiceClient;
// }
//
// interface FeaturedCatsState {
// error: Error | undefined;
// isLoaded: boolean;
// cats: Cat[];
// }
// You can destructure client to make things a little easier
// to understand. You’re using TypeScript and interfaces to
// achieve the same effect, but this also works.
//
const FeaturedCats = ({ client, ...props }) => {
const [state, setState] = React.useState({
isLoaded: false,
error: null,
cats: [],
})
// React.useEffect is a simple hook that ‘reacts’ to
// dependencies. Right now, this hook has one dependency;
// client.
//
// Everytime client changes, this hook would rerun. But
// for all intents and purposes, client is probably not
// going to change, so you can expect this hook to run
// once, when your component mounts.
//
React.useEffect(() => {
let req = new GetFeaturedCatsRequest();
const call = client.getFeaturedCats(req, null, (err: Error, response: GetFeaturedCatsResponse) => {
console.log(err, response);
// NOTE: You can probably collapse these three
// setState calls to once. But sometimes you want to
// separate them to keep things cleaner, easier to
// understand.
setState(current => {
...current,
isLoaded: true,
});
if (err) {
setState(current => {
...current,
error: err,
});
return;
}
setState(current => {
...current,
cats: response.getCatsList(),
});
});
call.on("status", (status: Status) => {
if (status.metadata) {
console.log("Received metadata");
console.log(status.metadata);
}
});
// NOTE: If you need to tear down any resources when
// your component unmounts, you can optionally return a
// function/closure. This is very similar to how defer
// works in Go.
//
// For example:
//
// return () => {
// client.defer()
// }
//
// Or:
//
// return client.defer
//
}, [client])
// You can collocate your loading, error states but you
// could also extract them as separate components like
// this:
//
// const LoadingState = ({ state, ...props }) => (
// <Box>
// {/* ... */}
// </Box>
// )
//
// And then simply return:
//
// return <LoadingState state={state} />
if (!state.isLoaded) {
return (
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="flex-start"
border={5}
borderRadius={5}
p={5}
textAlign="left"
>
<Box>
<Box>
<Heading
size="xl"
as="h2"
lineHeight="shorter"
fontWeight="bold"
fontFamily="heading"
>
Featured cats
</Heading>
</Box>
</Box>
<CircularProgress isIndeterminate color="gray.300"></CircularProgress>
</Box>
);
}
if (state.error) {
return (
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="flex-start"
border={5}
borderRadius={5}
p={5}
textAlign="left"
>
<Box>
<Box>
<Heading
size="xl"
as="h2"
lineHeight="shorter"
fontWeight="bold"
fontFamily="heading"
>
Featured cats
</Heading>
</Box>
</Box>
<Alert status="error">
<AlertIcon />
<AlertTitle mr={1}>Error</AlertTitle>
<AlertDescription>{state.error.message}</AlertDescription>
</Alert>
</Box>
);
}
return (
<>
<Box
display="flex"
flexDirection="column"
alignItems="center"
justifyContent="flex-start"
border={5}
borderRadius={5}
p={5}
textAlign="left"
>
<Box>
<Box>
<Heading
size="xl"
as="h2"
lineHeight="shorter"
fontWeight="bold"
fontFamily="heading"
>
Featured cats
</Heading>
</Box>
</Box>
</Box>
<Grid
justifyContent="center"
p={2}
gap={2}
templateColumns={"repeat(auto-fit, 224px)"}
>
{state.cats.map((value: Cat, index: Number, array: Cat[]) => {
return (
<Box
display="block"
borderRadius="lg"
backgroundColor="white"
pl={3}
pr={3}
pt={5}
pb={5}
shadow="sm"
width="max-content"
>
<Box shadow={0} border={0} borderRadius={0}>
<Image
height={200}
width={200}
fallbackSrc="data:image/jpeg;base64,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"
/>
<Box
display="flex"
flexDirection="row"
alignItems="center"
justifyContent="flex-start"
pt={3}
pl={1}
pr={1}
>
<Icon name="chat" mr={1} />
<Text fontSize="lg" textAlign="center" fontStyle="italic">
{value.getName()}
</Text>
</Box>
</Box>
</Box>
);
})}
</Grid>
</>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment