-
Notifications
You must be signed in to change notification settings - Fork 151
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
Conversation
8225a18
to
ef1b91e
Compare
Great Work @Dhaiwat10 🚀 |
package.json
Outdated
@@ -2,7 +2,7 @@ | |||
"name": "@web3-ui/root", | |||
"license": "MIT", | |||
"version": "0.0.0", | |||
"private": "true", | |||
"private": "false", |
There was a problem hiding this comment.
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.
There was a problem hiding this 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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
"build:components": "yarn workspace @web3-ui/components build", | ||
"build:hooks": "yarn workspace @web3-ui/hooks build", |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
"dev:components": "yarn workspace @web3-ui/components dev", | ||
"dev:hooks": "yarn workspace @web3-ui/hooks dev" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
storiesOf('Address', module).add('Default', () => <Address />); | ||
storiesOf('Address', module).add('Default', () => <Address value='This is an input' />); |
There was a problem hiding this comment.
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)
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 = { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to #33
packages/hooks/package.json
Outdated
"test:watch": "yarn test --watch", | ||
"test:coverage": "jest --coverage --colors --maxWorkers=2", | ||
"hygen": "hygen", | ||
"component:new": "hygen component with-prompt", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
packages/hooks/src/Provider.tsx
Outdated
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; |
There was a problem hiding this comment.
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:
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; |
There was a problem hiding this comment.
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.
packages/hooks/src/Provider.tsx
Outdated
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>(); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 @@ | |||
{ |
There was a problem hiding this comment.
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
There was a problem hiding this 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 😁
module.exports = { | ||
printWidth: 100, | ||
semi: true, | ||
singleQuote: true, | ||
trailingComma: 'es5', | ||
jsxSingleQuote: true, | ||
}; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
module.exports = { | ||
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], | ||
addons: ['@storybook/addon-links', '@storybook/addon-essentials'], | ||
framework: '@storybook/react', | ||
}; |
There was a problem hiding this comment.
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
packages/hooks/package.json
Outdated
"test": "jest --maxWorkers=2", | ||
"test:watch": "yarn test --watch", | ||
"test:coverage": "jest --coverage --colors --maxWorkers=2", | ||
"hygen": "hygen", |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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
"dev:components": "yarn workspace @web3-ui/components dev", | ||
"dev:hooks": "yarn workspace @web3-ui/hooks dev" |
There was a problem hiding this comment.
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
const value = React.useMemo( | ||
() => ({ | ||
connectWallet, | ||
signer, | ||
userAddress, | ||
disconnectWallet, | ||
connected, | ||
provider, | ||
network, | ||
chainId, | ||
}), | ||
[connectWallet, signer, userAddress, web3Modal, connected, provider, network, chainId] | ||
); |
There was a problem hiding this comment.
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:
- https://github.com/kentcdodds/old-kentcdodds.com/blob/319db97260078ea4c263e75166f05e2cea21ccd1/content/blog/how-to-optimize-your-context-value/index.md
- Preventing rerenders with React.memo and useContext hook. facebook/react#15156 (comment)
- https://kentcdodds.com/blog/how-to-optimize-your-context-value
I think we should just go with this for now and figure out a better pattern later, just wanted to throw that out there :)
There was a problem hiding this comment.
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
packages/hooks/src/hooks/index.ts
Outdated
@@ -0,0 +1 @@ | |||
export * from './useWallet'; |
There was a problem hiding this comment.
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:
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 { |
There was a problem hiding this comment.
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! 😆
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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.
packages/hooks/src/index.ts
Outdated
export * from './hooks'; | ||
export * from './Provider'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to previous comment:
export * from './hooks'; | |
export * from './Provider'; | |
export { useWallet } from './hooks'; | |
export { | |
Provider, | |
ProviderProps, | |
Web3Context, | |
Web3ContextType, | |
} from './Provider'; |
ef1b91e
to
4aa5d72
Compare
This PR initalizes the
hooks
package and adds some starter code in the form of auseWallet
hook.Known issues
useWallet
hook inside the storybook for thecomponents
package. It did not work. For some reason, when I loguseWallet
's contents all properties come out asundefined
. It works fine in the storybook for thehooks
package, though. Feel free to try both environments out yourself.Other changes
components
packageAddress
in thecomponents
packagepackage.json
Notes
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