
Building a Smart Passkey Wallet from scratch with ZKsync Native AA
IntroductionSmart Contract wallets have become very popular with the rise of account abstraction. Account abstraction allows you implementing any signature verification method, enabling your smartphones and computers to become transaction signers, instead of 12-word seed phrases everyone used to have. Additionally, many other programmable features can be attached to build more complex features (e.g spending limits). In this article we are going to build a very simple smart account wallet on Z...

Managing Typescript projects with Monorepo
Building services with lots of code becomes a problematic issue when your application’s scale gets larger. Most of the projects suffer from difficulty of making changes to the codebase after some time, which causes instability of features. Therefore, your application components should be atomic and easily modifiable. There are several ways doing this and most of the big companies utilize these methods. Typescript has lots of advantages on implementing the modularity, since most of the written...

Commit Signature Verification with GPG keys on GitHub
Most of our time is spent on GitHub as developers and we keep contributing to various projects - both open and closed source. There are dozens of GitHub automations are happening in some repositories, sometimes releasing new public versions for applications and libraries. However, we might be having a malicious code injected to the codebase with an unauthorized access to our computers. Signing commits help us preventing impersonation attacks where someone might try to make unauthorized change...
Software Engineer at Clave

Building a Smart Passkey Wallet from scratch with ZKsync Native AA
IntroductionSmart Contract wallets have become very popular with the rise of account abstraction. Account abstraction allows you implementing any signature verification method, enabling your smartphones and computers to become transaction signers, instead of 12-word seed phrases everyone used to have. Additionally, many other programmable features can be attached to build more complex features (e.g spending limits). In this article we are going to build a very simple smart account wallet on Z...

Managing Typescript projects with Monorepo
Building services with lots of code becomes a problematic issue when your application’s scale gets larger. Most of the projects suffer from difficulty of making changes to the codebase after some time, which causes instability of features. Therefore, your application components should be atomic and easily modifiable. There are several ways doing this and most of the big companies utilize these methods. Typescript has lots of advantages on implementing the modularity, since most of the written...

Commit Signature Verification with GPG keys on GitHub
Most of our time is spent on GitHub as developers and we keep contributing to various projects - both open and closed source. There are dozens of GitHub automations are happening in some repositories, sometimes releasing new public versions for applications and libraries. However, we might be having a malicious code injected to the codebase with an unauthorized access to our computers. Signing commits help us preventing impersonation attacks where someone might try to make unauthorized change...
Software Engineer at Clave

Subscribe to Farhad

Subscribe to Farhad
Share Dialog
Share Dialog


<100 subscribers
<100 subscribers
React plays a huge role in our software development lifecycle building front-end services. With the continuous enhancements in NextJS, power of React is combined with Server Side Rendering (SSR), becoming the lead in front-end industry. Although there are many other front-end libraries and frameworks came out in the latest years, such as Vue.js and Svelte, React is the most preferred, as can be seen from Figure 1.
![[Figure 1]: Source - State of JS 2022](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/d6bdbf0a52af648630f0dcd3e515e1cea43ffa38e13eef43d88537ae45c9a64c.png)
React is a Javascript library that passes the authority of the codebase to developers and allows many customizations. It means that you write the code based on your pattern and there are only a few rules that should be followed. Therefore, the strong sides of React is achieved when it’s various features are used correctly with a correct pattern. State management, code splitting, memoization, server side rendering and many other features should be carefully designed by developers. In this article, we will dive deep into built-in and custom hooks, taking a look at commonly made mistakes in real-world usage of them.
As it can be understood from the name, hook is kind of a connection between your application parts. It is used to connect various React features to your UI components.
React offers many built-in hooks which are available for developer’s usage without any dependency. For example, the useState hook declares a state variable inside the component that can be updated directly. There are many other built-in hooks which can be found in React documentation for hooks:
https://react.dev/reference/react/hooks
Custom hooks are more advance features, allowing an extension to built-in hooks. You are able to do anything you want with a custom hook, using the built-in and other custom hooks. For example, let’s say you are keeping a counter state in your component, using the useState built-in hook, and use it in multiple places. With a custom hook you can keep this state separately in single place and call it multiple times at multiple places without repeating yourself. The definition looks really similar to functions in programming right? Yes, hooks are very similar to functions, but the only difference is they can make use of built-in React hooks to build reusable code partitions. The only thing you should do to inform the React about custom hook definition is starting the function name with use prefix. Let’s write a custom hook as stated in this paragraph to implement a counter state:
/* useCounter.ts */
type ReturnType = {
counter: number;
increment: () => void;
decrement: () => void;
}
export const useCounter = (): ReturnType => {
// You are able to use built-in hook
const [counter, setCounter] = useState(0);
// Increments the counter state
const increment = () => {
setCounter((prevState) => prevState + 1)
}
// Decrements the counter state
const decrement = () => {
setCounter((prevState) => prevState - 1)
}
// Return anything useful for you
return { counter, increment, decrement }
}
And let’s use the hook we built in our component:
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
export const MyComponent = () => {
// Call the hook to achieve the returned values from useCounter hook
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
If you define another component and name it MyComponent2.tsx, you will be able to use exact the same useCounter hook in your code for various reasons. This is pretty much of it about custom hooks. You are probably already thinking of many other things that you can build with hooks to not repeat yourself and keep the core UI components clear. Let’s get into the commonly made mistakes by developers before you built your ideas to make sure that your code is fine.
As we mentioned above, the custom hooks should be named with the prefix of use keyword to help the React to understand what is going on. As far as you start your function name with use keyword, your definition is correct programmatically. However, you should try naming the hooks based on the feature it implements to help other developers understanding why the hook is defined. Assume that you are building a hook to keep whether the user has connected their crypto wallet to the website. You should probably choose a name like useIsWalletConnected to clearly describe the hook’s purpose. Additionally, it is kind of a convention to choose a name without a use keyword for assigned variable. For example, as you can see from the example below, the variable name of isWalletConnected is same the as useIsWalletConnected except the use keyword.
const isWalletConnected = useIsWalletConnected()
The hooks are only available inside other hooks and components. It is common mistake to call a hook inside a normal Javascript function. In some frameworks, especially in web, the linters and Typescript will warn you about this mistake:
![[Figure 2] Example error arises with an incorrect hook usage](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/0cb846e5103280726de2a39cd7cd4736afeed615ffd24cb257a6c43b6ded4e3d.png)
However, sometimes you are not warned about this mistake. For example, in React Native code, you are able to call the hook inside a non-hook function which is a very important point that you should avoid.
useEffect is a built-in hook in React that plays a huge role in component lifecycle. It allows you handling effects in component to synchronize your application state with external systems. You can read more about it from the link below.
https://react.dev/reference/react/useEffect
In a more general definition, the useEffect hook accepts two arguments, a function to be executed (1st argument) when one of the variables inside the dependency array (2nd argument) changes. The commonly made mistake is not adding a variable that is used inside useEffect to the dependency array. This causes a huge problem for the application state, since you are not accessing the latest values in the state. It is expected from developers to add all the used dependencies to the second argument of the useEffect hook. There is a really helpful eslint rule, called react-hooks/exhaustive-deps, to avoid making this mistake, which is built by React developers. I highly recommend using this eslint rule without ignoring it.
https://www.npmjs.com/package/eslint-plugin-react-hooks
We mentioned above about useEffect hook. Let’s also give another example to the common mistake while using the useEffect. This hook is sometimes used for event subscription in your component. Let’s say you want to register a listener to your smart contract and respond to the events that are emitted from it with Ethers.js. According to documentation, you should use contract.on method to listen to event. The correct place for this registration is useEffect for sure. Let’s implement it:
/* MyComponent.tsx */
export const MyComponent = () => {
useEffect(()=>{
// Create your callback function
const listener = () => {
console.log("Event Received")
}
// Create a new Ethers contract instance
const contract = new Contract("0xADDRESS", ABI, provider);
// Register event
contract.on("SomeEvent", listener)
}, [])
return ... // Some UI
}
According to the code written above, your listener function will be executed when the contract emits an event called SomeEvent. However, there is a problem. Let’s say your component is called inside a page, and after some time, you will navigate to different page. After the navigation happens, the event registration will still be active and listener function will be executed even if the MyComponent is not actively mounted on the screen. Additionally, when you come back to the page which uses MyComponent, the event registration will happen again, causing multiple subscriptions. Therefore, you should unregister this event to avoid this mistake. You can do this in return block of the useEffect. It is also known as componentWillUnmount() lifecycle in class components. You should follow the pattern below to unregister the subscription:
/* MyComponent.tsx */
export const MyComponent = () => {
useEffect(()=>{
// Create your callback function
const listener = () => {
console.log("Event Received")
}
// Create a new Ethers contract instance
const contract = new Contract("0xADDRESS", ABI, provider);
// Register event
contract.on("SomeEvent", listener)
// Unregister event
return () => {
contract.off("SomeEvent", listener)
}
}, [])
return ... // Some UI
}
Hooks are sometimes rendered conditionally inside the components. This is not a expected usage and should be avoided. What is a conditional rendering? Let’s see by giving the example of useCounter hook that we implemented above.
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
export const MyComponent = () => {
const [someState, setSomeState] = useState(true);
// Let's say you return an empty component when someState is false
if (!someState) {
return null;
}
// ERROR! Hooks should not be called conditionally
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
Instead, there are some tricky ways to render hooks conditionally. To do this you should create a separate React component and call the hook inside your component. Then, you can conditionally render this React component to also render the hook conditionally. Let’s see example below:
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
// Create a separate React component that calls the useCounter hook
const MyConditionalComponent = () => {
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
export const MyComponent = () => {
const [someState, setSomeState] = useState(true);
// Let's say you return an empty component when someState is false
if (!someState) {
return null;
}
/*
You can safely use the conditionally rendered component. With this way,
you are also rendering the useCounter hook in a conditional way.
*/
return <MyConditionalComponent />
}
Let’s say you are calling useCounter hook inside your component. It can sometimes be thought that, wherever you use the useCounter it will use the same state, just like a global variable. However, this is not correct. Every time you call a useCounter hook, it creates a new and separate counter state, as can be also seen from Figure 3, which is not connected with other counter states.
![[Figure 3] Multiple useCounter hook call](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/bc4217e8766f7e4f21702259e4df402d7a2e5d17851dc7dc3b65a5d192d39e98.png)
If you want to somehow achieve the global state structure to use the same values when calling custom hooks, you should either use React Context, which is built-in functionality of React, or third-party State Management Libraries. I highly recommend using Recoil, which is maintained by Meta team and has high performance.
Hooks can also be used to build various UI components. You can basically create a functional component inside a custom hook, return and use it. However, this is not an expected usage for custom hooks. Try keeping your components and hooks separately and do not use hooks to build UI components. You can build needed utilities with hooks and call them inside the UI component to keep them clear.
We covered 7 commonly made mistakes for React hooks in this article. These examples are mostly taken from my own past experience. I highly recommend taking these examples into consideration while building your custom hooks. Also, do not forget to always check React documentation for the correct information.
React plays a huge role in our software development lifecycle building front-end services. With the continuous enhancements in NextJS, power of React is combined with Server Side Rendering (SSR), becoming the lead in front-end industry. Although there are many other front-end libraries and frameworks came out in the latest years, such as Vue.js and Svelte, React is the most preferred, as can be seen from Figure 1.
![[Figure 1]: Source - State of JS 2022](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/d6bdbf0a52af648630f0dcd3e515e1cea43ffa38e13eef43d88537ae45c9a64c.png)
React is a Javascript library that passes the authority of the codebase to developers and allows many customizations. It means that you write the code based on your pattern and there are only a few rules that should be followed. Therefore, the strong sides of React is achieved when it’s various features are used correctly with a correct pattern. State management, code splitting, memoization, server side rendering and many other features should be carefully designed by developers. In this article, we will dive deep into built-in and custom hooks, taking a look at commonly made mistakes in real-world usage of them.
As it can be understood from the name, hook is kind of a connection between your application parts. It is used to connect various React features to your UI components.
React offers many built-in hooks which are available for developer’s usage without any dependency. For example, the useState hook declares a state variable inside the component that can be updated directly. There are many other built-in hooks which can be found in React documentation for hooks:
https://react.dev/reference/react/hooks
Custom hooks are more advance features, allowing an extension to built-in hooks. You are able to do anything you want with a custom hook, using the built-in and other custom hooks. For example, let’s say you are keeping a counter state in your component, using the useState built-in hook, and use it in multiple places. With a custom hook you can keep this state separately in single place and call it multiple times at multiple places without repeating yourself. The definition looks really similar to functions in programming right? Yes, hooks are very similar to functions, but the only difference is they can make use of built-in React hooks to build reusable code partitions. The only thing you should do to inform the React about custom hook definition is starting the function name with use prefix. Let’s write a custom hook as stated in this paragraph to implement a counter state:
/* useCounter.ts */
type ReturnType = {
counter: number;
increment: () => void;
decrement: () => void;
}
export const useCounter = (): ReturnType => {
// You are able to use built-in hook
const [counter, setCounter] = useState(0);
// Increments the counter state
const increment = () => {
setCounter((prevState) => prevState + 1)
}
// Decrements the counter state
const decrement = () => {
setCounter((prevState) => prevState - 1)
}
// Return anything useful for you
return { counter, increment, decrement }
}
And let’s use the hook we built in our component:
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
export const MyComponent = () => {
// Call the hook to achieve the returned values from useCounter hook
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
If you define another component and name it MyComponent2.tsx, you will be able to use exact the same useCounter hook in your code for various reasons. This is pretty much of it about custom hooks. You are probably already thinking of many other things that you can build with hooks to not repeat yourself and keep the core UI components clear. Let’s get into the commonly made mistakes by developers before you built your ideas to make sure that your code is fine.
As we mentioned above, the custom hooks should be named with the prefix of use keyword to help the React to understand what is going on. As far as you start your function name with use keyword, your definition is correct programmatically. However, you should try naming the hooks based on the feature it implements to help other developers understanding why the hook is defined. Assume that you are building a hook to keep whether the user has connected their crypto wallet to the website. You should probably choose a name like useIsWalletConnected to clearly describe the hook’s purpose. Additionally, it is kind of a convention to choose a name without a use keyword for assigned variable. For example, as you can see from the example below, the variable name of isWalletConnected is same the as useIsWalletConnected except the use keyword.
const isWalletConnected = useIsWalletConnected()
The hooks are only available inside other hooks and components. It is common mistake to call a hook inside a normal Javascript function. In some frameworks, especially in web, the linters and Typescript will warn you about this mistake:
![[Figure 2] Example error arises with an incorrect hook usage](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/0cb846e5103280726de2a39cd7cd4736afeed615ffd24cb257a6c43b6ded4e3d.png)
However, sometimes you are not warned about this mistake. For example, in React Native code, you are able to call the hook inside a non-hook function which is a very important point that you should avoid.
useEffect is a built-in hook in React that plays a huge role in component lifecycle. It allows you handling effects in component to synchronize your application state with external systems. You can read more about it from the link below.
https://react.dev/reference/react/useEffect
In a more general definition, the useEffect hook accepts two arguments, a function to be executed (1st argument) when one of the variables inside the dependency array (2nd argument) changes. The commonly made mistake is not adding a variable that is used inside useEffect to the dependency array. This causes a huge problem for the application state, since you are not accessing the latest values in the state. It is expected from developers to add all the used dependencies to the second argument of the useEffect hook. There is a really helpful eslint rule, called react-hooks/exhaustive-deps, to avoid making this mistake, which is built by React developers. I highly recommend using this eslint rule without ignoring it.
https://www.npmjs.com/package/eslint-plugin-react-hooks
We mentioned above about useEffect hook. Let’s also give another example to the common mistake while using the useEffect. This hook is sometimes used for event subscription in your component. Let’s say you want to register a listener to your smart contract and respond to the events that are emitted from it with Ethers.js. According to documentation, you should use contract.on method to listen to event. The correct place for this registration is useEffect for sure. Let’s implement it:
/* MyComponent.tsx */
export const MyComponent = () => {
useEffect(()=>{
// Create your callback function
const listener = () => {
console.log("Event Received")
}
// Create a new Ethers contract instance
const contract = new Contract("0xADDRESS", ABI, provider);
// Register event
contract.on("SomeEvent", listener)
}, [])
return ... // Some UI
}
According to the code written above, your listener function will be executed when the contract emits an event called SomeEvent. However, there is a problem. Let’s say your component is called inside a page, and after some time, you will navigate to different page. After the navigation happens, the event registration will still be active and listener function will be executed even if the MyComponent is not actively mounted on the screen. Additionally, when you come back to the page which uses MyComponent, the event registration will happen again, causing multiple subscriptions. Therefore, you should unregister this event to avoid this mistake. You can do this in return block of the useEffect. It is also known as componentWillUnmount() lifecycle in class components. You should follow the pattern below to unregister the subscription:
/* MyComponent.tsx */
export const MyComponent = () => {
useEffect(()=>{
// Create your callback function
const listener = () => {
console.log("Event Received")
}
// Create a new Ethers contract instance
const contract = new Contract("0xADDRESS", ABI, provider);
// Register event
contract.on("SomeEvent", listener)
// Unregister event
return () => {
contract.off("SomeEvent", listener)
}
}, [])
return ... // Some UI
}
Hooks are sometimes rendered conditionally inside the components. This is not a expected usage and should be avoided. What is a conditional rendering? Let’s see by giving the example of useCounter hook that we implemented above.
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
export const MyComponent = () => {
const [someState, setSomeState] = useState(true);
// Let's say you return an empty component when someState is false
if (!someState) {
return null;
}
// ERROR! Hooks should not be called conditionally
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
Instead, there are some tricky ways to render hooks conditionally. To do this you should create a separate React component and call the hook inside your component. Then, you can conditionally render this React component to also render the hook conditionally. Let’s see example below:
/* MyComponent.tsx */
// Import the custom hook (assuming useCounter.ts is in the same directory)
import { useCounter } from "./useCounter";
// Create a separate React component that calls the useCounter hook
const MyConditionalComponent = () => {
const { counter, increment, decrement } = useCounter()
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Increment</button>
</div>
)
}
export const MyComponent = () => {
const [someState, setSomeState] = useState(true);
// Let's say you return an empty component when someState is false
if (!someState) {
return null;
}
/*
You can safely use the conditionally rendered component. With this way,
you are also rendering the useCounter hook in a conditional way.
*/
return <MyConditionalComponent />
}
Let’s say you are calling useCounter hook inside your component. It can sometimes be thought that, wherever you use the useCounter it will use the same state, just like a global variable. However, this is not correct. Every time you call a useCounter hook, it creates a new and separate counter state, as can be also seen from Figure 3, which is not connected with other counter states.
![[Figure 3] Multiple useCounter hook call](https://img.paragraph.com/cdn-cgi/image/format=auto,width=3840,quality=85/https://storage.googleapis.com/papyrus_images/bc4217e8766f7e4f21702259e4df402d7a2e5d17851dc7dc3b65a5d192d39e98.png)
If you want to somehow achieve the global state structure to use the same values when calling custom hooks, you should either use React Context, which is built-in functionality of React, or third-party State Management Libraries. I highly recommend using Recoil, which is maintained by Meta team and has high performance.
Hooks can also be used to build various UI components. You can basically create a functional component inside a custom hook, return and use it. However, this is not an expected usage for custom hooks. Try keeping your components and hooks separately and do not use hooks to build UI components. You can build needed utilities with hooks and call them inside the UI component to keep them clear.
We covered 7 commonly made mistakes for React hooks in this article. These examples are mostly taken from my own past experience. I highly recommend taking these examples into consideration while building your custom hooks. Also, do not forget to always check React documentation for the correct information.
No activity yet