Skip to content

Conversation

@TheMaja
Copy link
Contributor

@TheMaja TheMaja commented May 15, 2023

Related issues: [please specify]

Description:

What are you up to? Fill us in :)

Screenshots/videos

I solemnly swear that:

  • My code follows the style guidelines of this project
  • I have merged the develop branch into my branch and fixed any merge conflicts
  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have tested new or existing tests and made sure that they pass

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start but has a few rough edges:

Always try to be explicit:

  1. Use of any. Please try not to use any. Rather be explicit. Otherwise when a new coder works on this stuff they will be encouraged to guess and there will be errors that come from that.
  2. Use of ReactNode when we can refer to a specific type.

Make sure you aren't making changes you don't meant to make. There are a few strange things in here.

I haven't actually run the code and looked for errors. Can you please check yourself for errors by running

  • npm run build
  • the storybook tests

The storybook tests use this https://storybook.js.org/docs/react/writing-tests/test-runner

You can run them by opening two terminals:

# terminal 1

npm run storybook

# terminal 2

npm run test-storybook

padding="md"
header={
<Header height={60} p="xs">
<Container></Container>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a container in the header now?

children: React.ReactNode;
serverSidePropsCorrectlyCalled: boolean;
isLoggedIn: boolean;
loggedInUserData: any;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loggedInUserData shouldn't be any

query,
req,
}: {
query: any;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These shoulnd't be any

query: any;
req: any;
}) {
const whoAmIResponse = await serverSideWhoAmI({ query, req } as any);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also not any

"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "components/LoggedOutPage.tsx"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at the existing patterns here. Do you think "components/LoggedOutPage.tsx" is actually helpful? Or do you think it is already included?

}

export function Underlined({ children }) {
export function Underlined({ children }: { children: React.ReactNode }) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at how these functions are used. Are you sure they take in any ReactNode or are they called with one specific type of node

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have some guesswork in here. Specifically, your use of GetServerSidePropsContext is dodgy.

In the face of ambiguity, refuse the temptation to guess

If you put guesses in your code then it will be hard for me to trust your code. Every time I've put in the up-front effort to understand things properly it's worked out well for me. Remember that part of the reason you are doing this work is so that you can level up and help others to level up.

One thing I'm not sure of myself if the difference between JSX.Element, ReactElement and ReactNode. So I'm going to need to research that before reviewing everything properly. If you feel like you made any guesses there then please revise that.

query,
req,
}: GetServerSidePropsContext) {
const whoAmIResponse = await serverSideWhoAmI({ query, req } as GetServerSidePropsContext);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a lot of guessing...

As far as I know, GetServerSidePropsContext looks like this:

 export interface GetServerSidePropsContext {
  req: IncomingMessage
  res: ServerResponse
  params?: ParsedUrlQuery
  query: ParsedUrlQuery
  preview?: boolean
  previewData?: any
}

serverSideWhoAmI returns something completely different to that. Just because it is used in server side things doesn't mean that the type is this random thing.

GetServerSidePropsContext is used like this only:

getServerSideProps = async ({ arguments,you,want }: GetServerSidePropsContext) => {
...

In other words, the arguments sent to a getServerSideProps function will adhere to that interface.

If you look at the return below, you can see these lines:

    isLoggedIn: whoAmIResponse.status === 200,
    loggedInUserData: whoAmIResponse.responseData,

This tells us that the whoAmIResponse at least has a status that can be a number, and responseData. The responseData would be a JSON response. So basically an object.

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some rough edges...

children: React.ReactNode;
serverSidePropsCorrectlyCalled: boolean;
isLoggedIn: boolean;
loggedInUserData: { firstName: string; email: string }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets copy-pasted all over the place now:

{ firstName: string; email: string }

What if we decide to add a lastName or a cellphoneNumber? Then we'll have to change the code in a million places.

Make an interface in one file, and then import it as needed.

Remember DRY

children,
}: {
handleLogout: () => void;
loggedInUserData: { firstName: string; email: string }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not DRY

const whoAmIResponse = await serverSideWhoAmI({ query, req });


export const getServerSidePropsForLoggedInPage = async (context: GetServerSidePropsContext) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explicit is better than implicit.

Are we really expecting the props to look like this?

It looks like we don't use most of that.

Good code makes its intentions clear. So it's important to be specific about what is required.

We are using Typescript so that when other coders work on this project they don't mess up and pass the wrong thing into a function. So we should not accept the wrong thing. We should only accept exactly the correct thing.

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some repeated comments. Please address everything.




const LoggedInUserDataType = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be an interface?

const whoAmIResponse = await serverSideWhoAmI({ query, req });


export const getServerSidePropsForLoggedInPage = async ({ query, req }: GetServerSidePropsContext) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mentioned this one multiple times now. If you do not understand a comment then please do not ignore the comment. I really don't like repeating myself this many times.

Look at how much information is inside GetServerSideProps:
https://github.com/vercel/next.js/blob/v10.2.0/packages/next/types/index.d.ts#L136-L151

if 90% of the interface is completely inaccurate then it's a bad choice.

Please use something appropriate here. GetServerSidePropsContext is inappropriate.

If you disagree then say so. Do not simply ignore this feedback.

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can do better

import { clearAuthToken } from "../lib/authTokenStorage";
import { useCookies } from "react-cookie";

interface Props {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The different components have different props. Please use different interfaces for the different things.

If the foo function has the arguments a, b and c and the bar function has d, e and f then it is incorrect to say that foo requires a,b,c,d,e, f, req and query.

Please make use of the correct interface. It should tell the truth of what is required in each function.. Each function requires different things. We need to be exact and specific. If you add in extra things that aren't needed at all then that makes it worse.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also make a point of importing things that are defined elsewhere in the code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and req is definitely not a string.

email: string;
};
handleLogout?: () => void;
req?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

req isn't used by any function here. Why is it in this interface at all?

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still one weird guess in here that I can see.

I need to learn about the different React children prototypes still so there is a chance I've missed something. Please triple-check that there is nothing else that you guessed on. I'm very keen to get this finished.

export function ErrorAlert({ children, title }) {
interface Props {
title: string;
children: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be better here to say that the children could be a string or another component. Eg if we wanted to have multiple paragraphs of text then a string wouldn't cut it. We would either use multiple Text components or a Stack with a bunch of Text components inside it.

export async function getServerSidePropsForLoggedInPage({ query, req }) {
const whoAmIResponse = await serverSideWhoAmI({ query, req });

export async function getServerSidePropsForLoggedInPage({ query, req }: { query: { [key: string]: string }, req: IncomingMessage }) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no reason to invent things here. Look:

type GetServerSidePropsContext<
  Q extends ParsedUrlQuery = ParsedUrlQuery
> = {
  req: IncomingMessage & { 
    cookies: NextApiRequestCookies
  }
  res: ServerResponse
  params?: Q
  query: ParsedUrlQuery
  preview?: boolean
  previewData?: PreviewData
  resolvedUrl: string
  locale?: string
  locales?: string[]
  defaultLocale?: string
}

This information comes from https://github.com/vercel/next.js/blob/v10.2.0/packages/next/types/index.d.ts#L136-L151

What datatype is query? What datatype is req? Please use those. We know where these props come from, we know exactly what the types are.

Copy link
Collaborator

@sheenarbw sheenarbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still one thing that looks inaccurate as far as I can see.

Also, this branch is not up to date with the latest code.

Please do the following:

  • fix the last inaccuracy
  • merge the latest develop branch into your branch and fix any merge conflicts that come up
  • make sure that the storybook tests still pass
  • make sure you can build the application. You can see how to run it by looking at package.json

req,
}: {
query: ParsedUrlQuery;
req: IncomingMessage;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use exactly this for req's type. There is no need to be creative here, we can just copy.

Is there a reason you want to leave out the part about the cookies?

req: IncomingMessage & {
    cookies: NextApiRequestCookies
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants