Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: setup hooks package #31

Merged
merged 1 commit into from
Nov 29, 2021
Merged

feat: setup hooks package #31

merged 1 commit into from
Nov 29, 2021

Conversation

Dhaiwat10
Copy link
Member

@Dhaiwat10 Dhaiwat10 commented Nov 29, 2021

This PR initalizes the hooks package and adds some starter code in the form of a useWallet hook.

Known issues

  • I tried using the useWallet hook inside the storybook for the components package. It did not work. For some reason, when I log useWallet's contents all properties come out as undefined. It works fine in the storybook for the hooks package, though. Feel free to try both environments out yourself.

Other changes

  • Removed an unnecessary story from the components package
  • Updated the story for Address in thecomponents package
  • Updated some scripts in the root package.json

Notes

  • I published v0.1.0 of @web3-ui/hooks to test out if there's a problem with the bundling and stuff is just not being compiled.

cc @etr2460

@Dhaiwat10 Dhaiwat10 linked an issue Nov 29, 2021 that may be closed by this pull request
@naz3eh
Copy link
Member

naz3eh commented Nov 29, 2021

I tried this out.
While running yarn, it gave me the below error.
image

Then I upgraded my node to version 16 and the error disappeared.
Except that everything LGTM.

Though I'd love to add more hooks.

@Canopix
Copy link

Canopix commented Nov 29, 2021

Great Work @Dhaiwat10 🚀

package.json Outdated
@@ -2,7 +2,7 @@
"name": "@web3-ui/root",
"license": "MIT",
"version": "0.0.0",
"private": "true",
"private": "false",
Copy link
Member

Choose a reason for hiding this comment

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

We want this to stay private, right? This should never be published because it's just a way to coordinate the other packages.

Copy link
Contributor

@etr2460 etr2460 left a comment

Choose a reason for hiding this comment

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

a few comments, nothing blocking, but mostly asking about how we want to handle the monorepo setup

.gitignore Outdated
/coverage

dist
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: let's add a newline to the end of the file

Copy link
Contributor

Choose a reason for hiding this comment

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

also, /dist/ is already used on line 3. let's remove that one and replace it with dist instead

Comment on lines +18 to +19
"build:components": "yarn workspace @web3-ui/components build",
"build:hooks": "yarn workspace @web3-ui/hooks build",
Copy link
Contributor

Choose a reason for hiding this comment

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

I think i mentioned this in the tests pr i mad, but it might be cleaner to share the build scripts and configs between he two packages. so we'd have a build command in the root json that runs rollup, and then you could pass in either packages/components or packages/hooks to the command to build a specific package, or it would just build both if nothing is passed. thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

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

@etr2460 that's def a good idea but I suggest creating a separate issue/PR for that. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

Added this to the list in #33

package.json Outdated
Comment on lines 22 to 23
"dev:components": "yarn workspace @web3-ui/components dev",
"dev:hooks": "yarn workspace @web3-ui/hooks dev"
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment as above for the storybook setup here. if we can share configuration, then we'll reduce the code and make it easier to apply updates/config changes to both packages without missing one

Copy link
Member

Choose a reason for hiding this comment

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

Created #32 and added to the list in #33


storiesOf('Address', module).add('Default', () => <Address />);
storiesOf('Address', module).add('Default', () => <Address value='This is an input' />);
Copy link
Contributor

Choose a reason for hiding this comment

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

minor nit, but i like my storybook components to contain real looking content. So something like this might look better (and make it more clear what the component is for)

Suggested change
storiesOf('Address', module).add('Default', () => <Address value='This is an input' />);
storiesOf('Address', module).add('Default', () => <Address value='testaddress.eth' />);

@@ -0,0 +1,7 @@
module.exports = {
Copy link
Contributor

Choose a reason for hiding this comment

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

should prettier files be consolidated in the root of the monorepo too?

Copy link
Member

Choose a reason for hiding this comment

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

Added to #33

"test:watch": "yarn test --watch",
"test:coverage": "jest --coverage --colors --maxWorkers=2",
"hygen": "hygen",
"component:new": "hygen component with-prompt",
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need this? it looks specific to components

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably not. I'll remove it

Comment on lines 8 to 15
connectWallet: (() => void) | undefined;
signer: JsonRpcSigner | null | undefined;
userAddress: string | null | undefined;
disconnectWallet: (() => void) | undefined;
network: string;
chainId: number | undefined;
connected: boolean;
provider: ethers.providers.Web3Provider | null | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

this is a styling preference, so no need to accept, but i find it easier to grok these when the shorthand for undefined is used, like this:

Suggested change
connectWallet: (() => void) | undefined;
signer: JsonRpcSigner | null | undefined;
userAddress: string | null | undefined;
disconnectWallet: (() => void) | undefined;
network: string;
chainId: number | undefined;
connected: boolean;
provider: ethers.providers.Web3Provider | null | undefined;
connectWallet?: (() => void);
signer?: JsonRpcSigner | null;
userAddress?: string | null;
disconnectWallet?: (() => void);
network: string;
chainId?: number;
connected: boolean;
provider?: ethers.providers.Web3Provider | null;

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah that def needs to be changed. Just laziness on my part. Wanted to ship this PR quick.

const [signer, setSigner] = React.useState<null | JsonRpcSigner>(null);
const [provider, setProvider] = React.useState<null | ethers.providers.Web3Provider>(null);
const [userAddress, setUserAddress] = React.useState<null | string>(null);
const [web3Modal, setWeb3Modal] = React.useState<null | Web3Modal>();
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the difference between null and undefined here? if this is only ever undefined or Web3Modal, then lets remove the null type

const { userAddress, provider } = context;
if (userAddress && provider) {
provider.lookupAddress(userAddress).then((address) => {
setEns(address as string);
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to handle an error case where the address isn't found?

Copy link
Member Author

Choose a reason for hiding this comment

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

No. In that case, the ens will simply be null which is fine.

@@ -0,0 +1,23 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

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

if #25 goes in, then this file will probably get deleted too in favor of the root version

Copy link
Member

@with-heart with-heart left a comment

Choose a reason for hiding this comment

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

A few suggestions but I think we could also just move forward with this and revisit things later. Whatever you wanna do 😁

Comment on lines +1 to +7
module.exports = {
printWidth: 100,
semi: true,
singleQuote: true,
trailingComma: 'es5',
jsxSingleQuote: true,
};
Copy link
Member

Choose a reason for hiding this comment

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

We only need one root .prettierrc for this to work across the workspace.

Also I think we should try to stick with the same config we've been using in the other projects just to make things consistent! printWidth: 100 and jsxSingleQuote: true are pretty non-standard generally imo

Copy link
Member Author

Choose a reason for hiding this comment

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

Great suggestion. I think this can be coupled with some other devops-y changes @etr2460 suggested in his reviews. We can batch these change together in a PR dedicated to that.

Comment on lines +1 to +5
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
framework: '@storybook/react',
};
Copy link
Member

Choose a reason for hiding this comment

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

I think we should combine hooks/.storybook and components/.storybook into a single Storybook instance at the root. We can leave this for now though and tackle combining them in #32

"test": "jest --maxWorkers=2",
"test:watch": "yarn test --watch",
"test:coverage": "jest --coverage --colors --maxWorkers=2",
"hygen": "hygen",
Copy link
Member

Choose a reason for hiding this comment

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

I think we should remove hygen from this PR and add it in a follow-up so we can discuss and document it. Seems interesting but it deserves its own space so we can all be on the same page about what it is and how to use it.

"test:coverage": "jest --coverage --colors --maxWorkers=2",
"hygen": "hygen",
"component:new": "hygen component with-prompt",
"pre-commit-hook": "yarn lint-staged",
Copy link
Member

Choose a reason for hiding this comment

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

We shouldn't need this here since we have the config at the root. I'm fine with moving forward with this and resolving it later as part of #33 though

package.json Outdated
Comment on lines 22 to 23
"dev:components": "yarn workspace @web3-ui/components dev",
"dev:hooks": "yarn workspace @web3-ui/hooks dev"
Copy link
Member

Choose a reason for hiding this comment

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

imo it'd be more familiar to call these storybook:components and storybook:hooks. dev is typically associated with running a development server which is sort of what Storybook is, but I think a lot of projects conceptualize storybook as a separate thing.

Running yarn storybook:components makes it pretty clear what you're running whereas dev is pretty ambiguous and it starting Storybook would imo be surprising to most

Comment on lines +79 to +90
const value = React.useMemo(
() => ({
connectWallet,
signer,
userAddress,
disconnectWallet,
connected,
provider,
network,
chainId,
}),
[connectWallet, signer, userAddress, web3Modal, connected, provider, network, chainId]
);
Copy link
Member

Choose a reason for hiding this comment

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

useMemo probably isn't helping in the way you think it is.

Some resources that might explain why/provide alternatives:

I think we should just go with this for now and figure out a better pattern later, just wanted to throw that out there :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for sharing these resources. Super helpful

@@ -0,0 +1 @@
export * from './useWallet';
Copy link
Member

Choose a reason for hiding this comment

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

One thing I've learned from experience is that it's better to be explicit with re-exports in index files:

Suggested change
export * from './useWallet';
export { useWallet } from './useWallet';

Anyone looking at this file can tell at a glance what is exported from this folder, whereas export * syntax requires them to read through each individual file to know what all is exported.

import WalletConnectProvider from '@walletconnect/web3-provider';
import Web3Modal from 'web3modal';

export interface Web3ContextType {
Copy link
Member

Choose a reason for hiding this comment

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

Web3ContextType

But it's not a type, it's an interface! 😆

Copy link
Member Author

Choose a reason for hiding this comment

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

classic

provider: ethers.providers.Web3Provider | null | undefined;
}

export const Web3Context = React.createContext<Web3ContextType | undefined>(undefined);
Copy link
Member

@with-heart with-heart Nov 29, 2021

Choose a reason for hiding this comment

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

We'll probably want to use a few tricks for defining this context so we (or our users) don't have to check for its existence all over the place before we can use it.

// without tricks 
const web3Context = useContext(Web3Context)
// gross
web3Context?.connectWallet()

// with tricks
const web3Context = useContext(Web3Context)
// yum
web3Context.connectWallet()

We'll get to it later!

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah this is a massive pain point.

Comment on lines 1 to 2
export * from './hooks';
export * from './Provider';
Copy link
Member

Choose a reason for hiding this comment

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

Similar to previous comment:

Suggested change
export * from './hooks';
export * from './Provider';
export { useWallet } from './hooks';
export {
Provider,
ProviderProps,
Web3Context,
Web3ContextType,
} from './Provider';

@Dhaiwat10 Dhaiwat10 merged commit e08bfe4 into master Nov 29, 2021
@Dhaiwat10 Dhaiwat10 deleted the feat/hooks-package branch December 6, 2021 07:13
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.

Setup the hooks package with some basic hooks
5 participants