Update from obsidian - thinkpad

Affected files:
.obsidian/app.json
.obsidian/graph.json
.obsidian/plugins/obsidian-omnivore/data.json
.obsidian/plugins/update-time-on-edit/data.json
01. Projects/Fuuka/Outline.md
01. Projects/Juuno/Outline.md
01. Projects/Renuncia/Renuncia.md
02. Areas/Dotfiles/dotfiles tasks.md
02. Areas/Escape Latam/Canada.md
02. Areas/Escape Latam/Comparación de Paises.md
02. Areas/Escape Latam/Escapar de Latam.md
02. Areas/Escape Latam/New Zeldand.md
03. Resources/Development/Feature shipment checklist.md
03. Resources/Development/Fix messy commits.md
03. Resources/Development/Git.md
03. Resources/Development/Iframes.md
03. Resources/Development/Revert old changes in a codebase.md
03. Resources/Development/Search for a bug.md
03. Resources/Notetaking/Habits.md
Read Later/2024-02-12 - Debouncing in JavaScript – Explained by Building Auto-Complete Functionality in React.md
notes/Git.md
This commit is contained in:
Alexander Navarro 2024-02-20 12:23:30 -03:00
parent c82f170ec4
commit c84ad03d4c
21 changed files with 573 additions and 61 deletions

2
.obsidian/app.json vendored
View file

@ -3,7 +3,7 @@
"showLineNumber": true,
"tabSize": 2,
"vimMode": true,
"newFileLocation": "folder",
"newFileLocation": "current",
"alwaysUpdateLinks": true,
"useMarkdownLinks": true,
"showUnsupportedFiles": true,

View file

@ -17,6 +17,6 @@
"repelStrength": 10,
"linkStrength": 1,
"linkDistance": 250,
"scale": 0.4952113402093565,
"scale": 0.3580284794893512,
"close": true
}

View file

@ -3,7 +3,7 @@
"dateSavedFormat": "yyyy-MM-dd HH:mm:ss",
"apiKey": "ec3bba50-4770-471b-99b1-9953ca523d8c",
"filter": "ADVANCED",
"syncAt": "2024-02-17T17:22:18",
"syncAt": "2024-02-20T12:01:36",
"customQuery": "in:archive has:highlights",
"template": "# {{{title}}}\n\n{{# note }}\n## Notes\n\n{{{ note }}}\n{{/ note }}\n{{#highlights.length}}\n## Highlights\n\n{{#highlights}}\n{{{text}}} \n{{#note}}\n\n> [!note]\n> {{{note}}}\n{{/note}}\n\n[source]({{{highlightUrl}}}) {{#labels}} #{{name}} {{/labels}}\n\n---\n\n{{/highlights}}\n{{/highlights.length}}\n## Original\n\n{{{ content }}}",
"highlightOrder": "LOCATION",
@ -17,7 +17,7 @@
"version": "1.6.3",
"isSingleFile": false,
"frequency": 60,
"intervalId": 13,
"intervalId": 14,
"frontMatterVariables": [],
"frontMatterTemplate": "id: {{{ id }}}\ntitle: >\n {{{ title }}}\nstatus: {{{ state }}}\ntags:\n - read-later\n{{#labels.length}}\n{{#labels}} - {{{name}}}\n{{/labels}}\n{{/labels.length}}\ndate_added: {{{ dateSaved}}}\nurl_omnivore: >\n {{{ omnivoreUrl}}}\nurl_original: >\n {{{ originalUrl}}}"
}

View file

@ -18,21 +18,16 @@
"notes/testo.md": "24df1da31f19afae3f434032b447e804a8bcbdeeb1b270c6d04f28bfba5583fb",
"notes/North Start.md": "662704939ce34782d6578cd8d91d5d7d738de19ce5eb34196f71733744bc1286",
"README.md": "10ebf3cf75edbc6a6ccaf5c000185cde1e70bdc86c13d5b150d06546bad9c4dc",
"01. Projects/Escape Latam/Comparación de Paises.md": "6fb41dde50e73d696948be100340f951fc490f40cbcdda45584719fd7ba57194",
"notes/Devlog.md": "8796c41169b072acea9ef97211e294ba7b464ccffabc1259c7763440fea7a63e",
"01. Projects/Obtener pasaporte/Obtener pasaporte.md": "f3c1769ca0f40f87c41954c48b4cc791cf77dc22422e15a7005a880d9b030de9",
"01. Projects/Escape Latam/Escapar de Latam.md": "4ac856a52471f5eb6923790a96bbbf9daa867137cf9b8add09f498ba87e4469e",
"01. Projects/Escape Latam/New Zeldand.md": "c46e7d6cb08da2a7d5500640abc560f5db37dd056561420bce56df1c6eb485c7",
"01. Projects/Escape Latam/Canada.md": "974bdb92354ff2d46e67f524390bce477c8b0f753012f4f86eb0d4291b10a6ce",
"02. Areas/Dotfiles/dotfiles tasks.md": "bc454043d61c51de530e28dafe5b296077159e19b8c492f6d7de0d455b28bf32",
"01. Projects/Renuncia/Renuncia.md": "17d174d61ae84b4f1393490e5ea89832cc28b1aa7a53ec78016ea30a1fccdcd2",
"02. Areas/Dotfiles/dotfiles tasks.md": "9b662ba9122aaff0817522108a3a2dce6ee203b7f2c58abc8f4934e3899d878a",
"01. Projects/Renuncia/Renuncia.md": "088263e8c8b8719835e203690683861cd889b1c2a1bf17bdfa09243b8eadbe53",
"01. Projects/Página Personal/board.md": "5ccecc6fd345d2e5361e6a55837716753426acbb020e4adcce89fc71c7d0b812",
"02. Areas/Food/recipes.md": "320958ea965e90d56fd07f79928b046ce07755df3c05fe965a115c305aac3b07",
"notes/asd.md": "e791e564d80d7b1354ef6dc05dab000a6ac265518f348d18db855d51264a8671",
"notes/Git.md": "33954c7b2255a032d400a87bcec9801fe8251583c092a383bd57f8571e9c7a90",
"01. Projects/Electronic Mantainance/List of electronics.md": "cadf1bbd65c88be9d11f8992a4315c24e4a6d14b53b8f197159975217c2e347c",
"01. Projects/Fuuka/Outline.md": "6f86cc6dc7ccaa67aca79992e152584ccfe4d73ff0c259e67625c67ded5a47fa",
"01. Projects/Juuno/Outline.md": "6bb923894b595091a1d536e77b51b415ef7e69c0d95d59192c134ab23703b42d",
"01. Projects/Fuuka/Outline.md": "4a78de980ff0aa4f449ae017423b2a86be6a52f8e9f7594034bdf8fd9974de6d",
"01. Projects/Juuno/Outline.md": "c31e2610673db2be6e3064478a37e0dd44cd5cb107bc3c6b70f109467110a51f",
"03. Resources/Notetaking/12. Questions.md": "a44916b14a0dd6f11280563bf77918df603b27bc1b43be7d4d41a9e71570cb3e",
"03. Resources/Notetaking/CODE Method.md": "76e12aafc17b46efb83b49d0f4f9abe0aaa132770db931766a8cccebfa6a88ec",
"03. Resources/Notetaking/North Start.md": "97cc810bb0609df94559cad725c88caec10b4bed33e220451ee6a4a05abb71de",
@ -44,6 +39,17 @@
"03. Resources/Notetaking/PARA method.md": "6b97f39b4fb42c6f9cdf52abb0221f9d802e163019fbc53d1a618d02e6ab2aaf",
"03. Resources/Notetaking/Progresive Summarization.md": "9236f0faf755cc57e1d6e548f0727f6a2909cc847f8afbef3dc14fa43efa7a44",
"01. Projects/Playa/comida.md": "0c27a53d357c1ffab1d4e6bf98545923dc211004041a3233528164ca47b0ef25",
"01. Projects/Playa/Comprar.md": "28114ba2502978f1a5a748766ed312dead7472155961ece2cf4b82aee13de322"
"01. Projects/Playa/Comprar.md": "28114ba2502978f1a5a748766ed312dead7472155961ece2cf4b82aee13de322",
"03. Resources/Notetaking/Habits.md": "2b6688471702b678ce2a8872ef86049592be866948871d8d3fbca5186f663d93",
"03. Resources/Development/Git.md": "f019123de154b2b1ea6bb2e60b7f0fe25094c9084c257c04c5e10f1fae0a7126",
"03. Resources/Development/Fix messy commits.md": "b1cd788af785ff651eed230eb313b09e984356de8bc2f1ab16b6858e2e5c6acf",
"03. Resources/Development/Revert old changes in a codebase.md": "6f2cd7c745d01436eac6ec8360de8085a7f1232f9fd3c21346e1a9ad15800dd2",
"03. Resources/Development/Search for a bug.md": "627a609a636453bd9de584ad559ea83338076fe656c08c90604f6551f79cab20",
"03. Resources/Development/Feature shipment checklist.md": "e6667e273f6553b4418039564f02dc51d5e83c5455d202cae4daf333914911be",
"03. Resources/Development/Iframes.md": "858ffe616925f94e6bfca207282649b111f134e30c67a76ddd0479c4f6193761",
"02. Areas/Escape Latam/Canada.md": "974bdb92354ff2d46e67f524390bce477c8b0f753012f4f86eb0d4291b10a6ce",
"02. Areas/Escape Latam/Comparación de Paises.md": "6fb41dde50e73d696948be100340f951fc490f40cbcdda45584719fd7ba57194",
"02. Areas/Escape Latam/Escapar de Latam.md": "4ac856a52471f5eb6923790a96bbbf9daa867137cf9b8add09f498ba87e4469e",
"02. Areas/Escape Latam/New Zeldand.md": "c46e7d6cb08da2a7d5500640abc560f5db37dd056561420bce56df1c6eb485c7"
}
}

View file

@ -1,9 +1,11 @@
---
created: 2024-02-10 09:43
updated: 2024-02-18 15:29
updated: 2024-02-20 11:23
---
## Maybe
- Sería interesante tener un chat en el landing junto al "song request"
- En el setup entre juno y fuuka en un docker-compose.yml, tendrá menos latencia montar un socket que por TCP?
- Implementar un "path mapping" similar a "arr's suit"
- Add meilisearch DB on top to add a "search bar" for music
- Add the option to allow or deny the song request while a playlist is playing

View file

@ -1,8 +1,9 @@
---
created: 2024-02-10 09:45
updated: 2024-02-18 15:29
updated: 2024-02-20 11:48
---
- Juno sólo necesita que los archivos de música existan cuándo se le solicite ejecutarlo.
- Randomize queue, diferente de shuffle mode
- randomize, re-order the current queue in a random way
- shuffle, pick the next song at random from the current queue
- I can use [fd](https://github.com/sharkdp/fd) as reference for the filesystem exploration code

View file

@ -1,5 +1,5 @@
---
created: 2024-02-06 14:27
updated: 2024-02-18 15:29
updated: 2024-02-20 11:50
---
- Con el finiquito puedo puedo ir a la AFC y obtener el seguro de cesantía en cuotas, que da más lucas.

View file

@ -1,6 +1,6 @@
---
created: 2024-02-06T14:24:00-03:00
updated: 2024-02-18 15:29
updated: 2024-02-20 11:52
type: Checklist
---
@ -10,3 +10,16 @@ type: Checklist
- [ ] Añadir undo-tree to nvim
- [ ] Terminar de configurar LF
- [ ] Add mpv compact osd
- [ ] revisar default merge strategy for git
- [ ] Cambiar tipo de ventana para neogit
- [ ] Revisar [plugin](https://github.com/vimpostor/vim-tpipeline) to unify nvim and tmux status line
- [ ] Revisar ansible para inicializar dots
- [ ] Test out Ollama to see if resource usage is too high
## Obsidian
- [ ] Revisar plugins
- [ ] Media DB plugin
- [ ] Obsidian Tasks
- [ ] Obsidian Index Folder

View file

@ -0,0 +1,9 @@
---
created: 2024-02-20 11:39
updated: 2024-02-20 11:42
---
When a feature or module is shipt, I need to asure the following things before submiting:
- Clean & readable code
- Linter without errors
- Design is as close as posible to the proposal

View file

@ -0,0 +1,25 @@
---
created: 2024-02-20 11:27
updated: 2024-02-20 11:31
tags:
- dev-tools
---
# Fix messy commits
Ya que estas opciones sobre escriben el historial de git, solo deben aplicarse en local y no commits publicados a un remote.
Como alternativa se puede intentar actualizar el historial remoto siempre y cuando el historial sea igual al local (osea, nosotros fuimos los últimos en actualizarlo y nadie ha hecho nada más). Para esto utilizamos `git push --force-with-lease`.
## Last commit
Si solo necesitamos agregar un cambio pequeño al ultimo commit (typo o correr el formatter), podemos aplicarlo con `git commit --ammend`, se puede sobre escribir el mensaje con `-m`.
## Mutiple commits
Se pueden arreglar el historial de commits con un `git rebase -i [since commit or branch]` y utilizar las estrategias de pick, squash, reword y drop.
En caso de que sepamos que haremos un commit que luego no necesitaremos, podemos hacer:
- `git commit --fixup [commit hash]` -> descarta el commit message de este commit y mantiene el del commit de referencia
- `git commit --squash [commit hash]` -> git juntará los mensajes de todos los commits a hacer squash y el commit de referencia.
Finalmente podemos hacer `git rebase -i --autosquash` y git eligirá las opciones necesarias a tomar en vez de tener que hacerlo de manera manual.

View file

@ -0,0 +1,15 @@
---
created: 2024-02-13 22:36
updated: 2024-02-20 11:38
tags:
- dev-tools
---
## Merge strategies
![Git Merge vs Rebase vs Squash ¿Qué estrategia debemos elegir](2023-11-04%20-%20Git%20Merge%20vs%20Rebase%20vs%20Squash%20¿Qué%20estrategia%20debemos%20elegir-.md#notes)
![Utilizar `git bisect`](Search%20for%20a%20bug.md#Utilizar%20`git%20bisect`)
![Fix messy commits](Fix%20messy%20commits.md)
![Revert old changes in a codebase](Revert%20old%20changes%20in%20a%20codebase.md)

View file

@ -0,0 +1,24 @@
---
created: 2024-02-20 11:43
updated: 2024-02-20 11:45
---
## How to make an Iframe 100% it's parent width while maintaining the aspect ratio
In this example, we need to wrap the iframe in a container class and provide the following styles:
```css
.container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
```

View file

@ -0,0 +1,15 @@
---
created: 2024-02-20 11:34
updated: 2024-02-20 11:34
tags:
- dev-tools
---
## Revertir cambios
Si necesitamos _"deshacer"_ los cambios introducidos en uno o multiples commits, podemos utilizar `git revert --no-edit older_commit_hashˆ..newer_commit_hash`, donde:
- git realizará un nuevo commit con los cambios contrarios por cada commit en el rango
- utilizar `ˆ` en el `old_commit_hash` incluirá ese commit en la reversión de cambios, si no se agrega se empezará a revertir de un commit más adelante.
- `--no-edit` es utilizado para que git no nos pregunte por el message de cada nuevo commit
- primero debe ser el commit más antiguo, porque git creará nuevos commits en orden provisto y de hacerlo al revés aparecerán conflictos
- si solo se quiere revertir un commit, se puede especificar solo ese hash

View file

@ -0,0 +1,9 @@
---
created: 2024-02-20 11:35
updated: 2024-02-20 11:37
---
# Buscar cuando un bug se introdujo
## Utilizar `git bisect`
`git bisect` hará un _"binary search"_ entre 2 commits, dejandonos señalar si este commit es _"bueno"_ (no tiene el bug) o _"malo"_ (tiene el bug), permitiendo encontrar el commit que introdujo el bug y facilitar encontrar la causa de este.

View file

@ -0,0 +1,22 @@
---
created: 2024-02-20 11:14
updated: 2024-02-20 11:18
---
# Habits to apply while notetaking process
## Project checklist
### Kickoff
### Completion
## Periodic reviews
This should be forgiving, doesn't bad happens if I miss a review day
### Weekly
### Monthly
## Noticing other habits
Do this inh small chunks while using the second brain

View file

@ -0,0 +1,412 @@
---
id: d529f41a-ca28-11ee-97f3-f78c291f6623
title: |
Debouncing in JavaScript Explained by Building Auto-Complete Functionality in React
status: ARCHIVED
tags:
- read-later
- RSS
date_added: 2024-02-12 20:23:30
url_omnivore: |
https://omnivore.app/me/debouncing-in-java-script-explained-by-building-auto-complete-fu-18da0bc7510
url_original: |
https://www.freecodecamp.org/news/deboucing-in-react-autocomplete-example/
---
# Debouncing in JavaScript Explained by Building Auto-Complete Functionality in React
## Highlights
Debouncing accepts a function and transforms it in to an updated (debounced) function so that the code inside the original function is executed after a certain period of time.
[source](https://omnivore.app/me/debouncing-in-java-script-explained-by-building-auto-complete-fu-18da0bc7510#2c8f31bd-f011-49bd-99bc-36192f7fd823)
---
function debounce(func, delay) {let timeout=null return (...args) => {if(timeout) clearTimeout(timeout) timeout=setTimeout(() \=> { func(...args) timeout=null }, delay) } }
[source](https://omnivore.app/me/debouncing-in-java-script-explained-by-building-auto-complete-fu-18da0bc7510#5a57c802-520a-409a-a51c-e554a6ec8bd5)
---
const useDebounce = (func, delay) => { let timeout\=null return (...args) => {if(timeout) clearTimeout(timeout)timeout\=setTimeout(() => { func(...args) }, delay) } }export default useDebounce
[source](https://omnivore.app/me/debouncing-in-java-script-explained-by-building-auto-complete-fu-18da0bc7510#226d8c7b-6900-4b2f-a705-5f5b6e10afc5)
---
## Original
![Debouncing in JavaScript Explained by Building Auto-Complete Functionality in React](https://proxy-prod.omnivore-image-cache.app/2000x1333,st8a8yNqtoznuGhyo0BqzXJQ0cEap88iHr4kvlN3Ff1Y/https://www.freecodecamp.org/news/content/images/size/w2000/2024/02/photo-1550063873-ab792950096b.jpeg)
Hi readers, I hope you are doing great! I am back with another tutorial on web development. If you are someone who enjoys developing web apps with JavaScript and React, then this post is for you.
When you roll out a new app into production, you want to make sure that it's user friendly. A website's performance is a key part of the user experience. Every user wants the website and its contents to load quickly. Each and every second is valuable and could result into a user never visiting your website again.
In this guide, we are going to understand a very important technique in JavaScript known as debouncing. Then, I will show you how to implement the autocomplete functionality in React with debouncing.
Now, in order to get the most out of this tutorial, I am assuming you have a basic knowledge of JavaScript. If you need to get started or review, here are a couple resources for you:
* Learn JavaScript basics [handbook for beginners](https://www.freecodecamp.org/news/learn-javascript-for-beginners/)
* The freeCodeCamp [JavaScript Algorithms and Data Structures certification](https://www.freecodecamp.org/news/learn-javascript-with-new-data-structures-and-algorithms-certification-projects/)
## **Table of Contents:**
* [What is Debouncing?](#what-is-debouncing)
* [How to Implement Debouncing in JavaScript](#how-to-implement-debouncing-in-javascript)
* [Use Case of Debouncing](#use-case-of-debouncing)
* [Conclusion](#conclusion)
## What is Debouncing?
Debouncing is a strategy used to improve the performance of a feature by controlling the time at which a function should be executed.
==Debouncing accepts a function and transforms it in to an updated (debounced) function so that the code inside the original function is executed after a certain period of time.==
If the debounced function is called again within that period, the previous timer is reset and a new timer is started for this function call. The process repeats for each function call.
An example will help you understand better. Let's take a function `fun()`. We want this function to execute after 500ms.
```crystal
function fun() {
console.log('This is a function')
}
```
After debouncing, a new function `debouncedFun()` is returned. Now, whenever you call `debouncedFun()`, it will be called after 500ms.
If you call it again within the next 500ms after first calling it, the previous timer is reset and a new timer is started for the second function call. The process repeats if you keep calling the function within 500ms.
## How to Implement Debouncing in JavaScript
Let's understand how to implement debouncing in JavaScript. First, we'll go over our requirements. What behavior do we want from the debounced function?
* Delay the function execution by a certain time, `delay`.
* Reset the timer if the function is called again.
To debounce a function, we'll have a separate function that accepts the function reference and the delay as parameters, and returns a debounced function.
```ada
function debounce(func, delay) {
return () => {} // return debounced function
}
```
This function will only be called once to return a debounced function and that, in turn, will be used in the subsequent code.
To delay a function by some milliseconds, we can simply use the `setTimeout` function in JavaScript.
```arcade
function debounce(func, delay) {
return () => {
setTimeout(() => {
func()
}, delay)
}
}
```
This delays the function call by `delay` milliseconds. But this is incomplete as it only satisfies the first requirement. How do we achieve the second behaviour?
Let's create a variable `timeout` and assign it to the return value of `setTimeout` method. The `setTimeout` method returns a unique identifier to the timeout, which is held by `timeout` variable.
```javascript
function debounce(func, delay) {
let timeout=null
return () => {
timeout=setTimeout(() => {
func()
}, delay)
}
}
```
Each time you invoke `setTimeout`, the ID is different. We will use this `timeout` variable to reset the timer.
But how do we get access to `timeout` from outside the `debounce()` method? As mentioned before, `debounce()` is only used once to return a debounced function. This, in turn, performs the debouncing logic.
Then, how does the debounced function have access to `timeout` even if it is used outside the `debounce()` function? Well, it uses a concept called closure.
### What's a closure in JavaScript?
In JavaScript, an inner function always has access to the local variables of the outer function. In our case, the inner function has access to `timeout` that has function level scope in the `debounce()` method.
But when the outer function returns this inner function, the inner function still holds a reference to the local variables of the outer function long after the outer function has finished execution. This is the concept of a closure.
Let's understand closures with an example.
```javascript
function outerFunction() {
const x = 5;
return () => {
console.log(x);
}
}
const inner = outerFunction();
inner(); // prints 5
// console.log(x) Throws reference error
```
Here, if we call `inner()`, the code runs without any errors and prints 5\. But, if we try to access `x` directly, JavaScript throws a reference error.
![Screenshot-2024-02-09-141749](https://proxy-prod.omnivore-image-cache.app/691x199,sr83BH8L2pwjWfvF3o3ztAC_Fg8t5J_j8jc8rZM45-I8/https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-09-141749.png)
JavaScript Reference Error
Here, `inner()` closes over `x` and only this function can use the variable and no one other one can. We cannot access the variable explicitly.
You can check out [this beginner-friendly tutorial](https://www.freecodecamp.org/news/closures-in-javascript/) to learn more about closures.
### Back to Debouncing
Let's get back to where we left off:
```javascript
function debounce(func, delay) {
let timeout=null
return () => {
timeout=setTimeout(() => {
func()
}, delay)
}
}
```
Here, JavaScript uses a closure to hold access to `timeout` every time we use the debounced function.
Let's use this to our advantage. Since `debouncedFun()` has access to the same `timeout` variable in every function call, we can add a condition to check whether a previous timeout exists. We can simply do this with a null check, `if(timeout !== null)` or `if(timeout)`.
Then, we use the `clearTimeout()` method to cancel the previous timeout, thus resetting the timer.
Add the following statement before starting a new timeout:
```lisp
if(timeout)
clearTimeout(timeout)
```
Once the timeout is reset, a new timeout is started for the current function call, whose ID is then assigned to `timeout`. The process is repeated for the subsequent function calls who have access to the same `timeout` due to closures.
```javascript
function debounce(func, delay) {
let timeout=null
return () => {
if(timeout) clearTimeout(timeout)
timeout=setTimeout(() => {
func()
}, delay)
}
}
```
With this, we have satisfied our second requirement that is, resetting the timer and starting a new one. It's time to use this debounced function.
Let's pass `fun()` to the `debounce()` method with a delay of 500ms.
```kotlin
const debouncedFun = debounce(fun, 500)
```
`debouncedFun()` is basically `fun()` with debouncing behaviour. Let's call this function at different time intervals to test our functionality.
```stylus
debouncedFun()
setTimeout(debouncedFun, 300)
setTimeout(debouncedFun, 900)
```
The first function call is made instantly. The other two are made after 300ms and 900ms respectively. Can you guess the output?
The code prints `This is a function` two times. Let's understand why. Here, after the first call is made, `fun()` is scheduled to execute after 500ms. But the second one is made in 300ms which resets the timer and starts a new one.
500ms have passed and the `fun()` method executes. Then, at 900ms, another function call is made. This again executes `fun()` after 500ms.
There is still a small improvement we should make. Our logic does not consider function arguments. Let's replace `fun()` with `fun(a, b)`.
```javascript
function fun(a, b) {
console.log(`This is a function with arguments ${a} and ${b}`)
}
```
To incorporate arguments while debouncing, return a debounced function that accepts arguments.
```javascript
function debounce(func, delay) {
let timeout=null
return (...args) => {
if(timeout) clearTimeout(timeout)
timeout=setTimeout(() => {
func(...args)
timeout=null
}, delay)
}
}
```
By using the spread operator, any arguments passed to the debounced function will be stored as an array in the `args` variable. Then, spread out the same `args` array to call the actual function with the arguments passed.
```kotlin
const debouncedFun=debounce(fun, 500)
debouncedFun(2,3)
```
The above code prints `This is a function with arguments 2 and 3` after 500ms.
## Use Case of Debouncing
Let's see how debouncing is used in practical applications. The most common use case of debouncing is the autocomplete functionality. You must have seen many websites where you type into an input field and it shows a list of results as you type them.
Here's an example from Google Search:
![Screenshot-2024-02-09-163240](https://proxy-prod.omnivore-image-cache.app/1462x487,s2SiKOKcVhwfHi5VYnRJVYbQ5pPYw6Qo8YMUAIGDxKzs/https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-09-163240.png)
Google Search Autocomplete after typing in "Top 10"
Google search shows the most recent and commonly searched terms. The information is mostly fetched from the browser cache. But, several websites make API calls to backend server to fetch the data from a database.
This can easily be implemented by adding an `onchange` event to the `input` element and implementing the fetch logic in the event handler. But there's a slight issue with this.
Consider the following example:
![Screenshot-2024-02-09-163930](https://proxy-prod.omnivore-image-cache.app/1915x882,sAcuTnmrT0AUE51eNXOrpzFo5aQn4QNd8NLdDhqrwkD0/https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-09-163930.png)
API Request made for each input value
When I type the word _absolute_, an API request is made every time the value of the input field changes. We are making 8 API requests in very few milliseconds which puts a lot of load on the backend server and could cause performance issues.
Ideally, we want to show the auto-complete results some time after the user has finished typing. Here, the user has typed _absolute_ in one go, so instead of showing results every time the input changes, we could show them once the user has finished typing that is, we could add some delay between the input change and the results being displayed.
So, we only make the API calls when the user finishes typing their word and not on every input change. This reduces the number of API calls and improves performance. We can achieve this behavior with debouncing.
Let's understand how to implement the autocomplete functionality in React.
### Auto-complete example
Use `create-react-app` (or a modern build tool like Vite) to create the project. Remove the existing boilerplate code. There is no need to install any additional dependencies. Run `npm start` command to start the project. You can find the complete code on [GitHub](https://github.com/KunalN25/react-debouncing).
I have set up a Node server to fetch data for the app. You can find it in the Git repo. Run the `node server` command to start it. I am not going to show the Node.js code as it's out of the scope of this tutorial.
Let's get started with the implementation. We will write a simple autocomplete functionality. The app should show a list of cities that contain an input string typed by the user.
#### App Component
We'll first need an `input` element to accept user input and a _results container_ for the search results. Attach an event handler to the `input` element which is an `async` function since it will include the fetching logic.
```javascript
function App() {
const [data, setData] = useState(null)
const loadData = async (event) => {
}
return (
<div className="App">
<input type="text" onChange={(e) => loadData(e)}/>
{data && data.length !== 0 &&
<div className="results-container">
{data.map(item => (
<div key={item.id} className="result-item">
<p> {item.city} </p>
</div>
))}
</div>}
</div>
);
}
```
The data will be stored as state and the results will only be shown if the data is non-empty. I'll skip over the CSS for this tutorial, you can find it in the [Git Repo](https://github.com/KunalN25/react-debouncing).
#### Event Handler
The `loadData()` function fetches our data and stores the response as state.
```cs
const loadData = async (event) => {
const value=event.target.value
if(value === '') {
setData(null)
return
}
const response=await fetch(`http://localhost:8000/data/${value}`)
const res=await response.json()
setData(res)
}
```
If no value is entered, simply exit the function. Else, make the request to the node server endpoint. This function is called every time the input changes, so we will debounce this function.
#### Debounce Implementation using a Custom Hook
We will write the debouncing logic inside a custom hook. The advantage of custom hooks is that you can re-use the same logic throughout your application. It is highly advisable to do so.
Create a new folder `custom-hooks` and inside it, create a file `useDebounce.js`. As explained before, the `useDebounce()` method should take a function and delay as parameters and return the debounced function.
```routeros
const useDebounce = (func, delay) => {
let timeout=null
return (...args) => {
if(timeout) clearTimeout(timeout)
timeout=setTimeout(() => {
func(...args)
}, delay)
}
}
export default useDebounce
```
Now, inside the app component, call this method once to get `loadDataDebounced()`.
```angelscript
const loadDataDebounced = useDebounce(loadData, 400)
```
We'll use this new method as the event handler for the `input` element.
```reasonml
<input type="text" onChange={(e) => loadDataDebounced(e)}/>
```
#### Output
Enter a search string inside the `input` element to test our code.
![Screenshot-2024-02-09-190240](https://proxy-prod.omnivore-image-cache.app/835x564,sb5zP6lXJrIxE_8ItjnafuRCnKNnHRzFsCN62XGBrLfQ/https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-09-190240.png)
On-screen output
![Screenshot-2024-02-09-191234](https://proxy-prod.omnivore-image-cache.app/1283x452,sHxsFT2-w6tk2KBgte1fwMNck9ai0l4qA7S8k1fzQDew/https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-09-191234.png)
As you can see in the Network tab, only one request is getting sent instead of three. This makes the search performance much better.
## Conclusion
In this tutorial, you learned what debouncing is and how it is implemented. Debouncing delays the function execution by a certain time and resets the previous timer if the function is called again.
Debouncing uses the important concept of closures. I took a slight detour from the implementation to explain what closure is. It can be a confusing concept for beginners, so take your time understanding it. Closures allow you to work with local variables even after a function has finished execution.
After that, I showed you a popular use case of debouncing, the auto-complete functionality. The performance of the feature can be improved with debouncing. I also showed you how to implement auto-complete in React and use debouncing with custom hooks. I hope this helps you in future projects.
If you are unable to understand the content or find the explanation unsatisfactory, let me know. New ideas are always appreciated! Feel free to connect with me on Twitter. Till then, Goodbye!
---
---
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. [Get started](https://www.freecodecamp.org/learn/)

View file

@ -1,41 +0,0 @@
---
created: 2024-02-13 22:36
updated: 2024-02-18 15:29
tags:
- dev-tools
---
## Merge strategies
![Notes](Git%20Merge%20vs%20Rebase%20vs%20Squash%20¿Qué%20estrategia%20debemos%20elegir-.md#Notes)
## Buscar cuando un bug se introdujo
Utilizar `git bisect`
## Fix messy commits
Ya que estas opciones sobre escriben el historial de git, solo deben aplicarse en local y no commits publicados a un remote.
### Last commit
Si solo necesitamos agregar un cambio pequeño al ultimo commit (typo o correr el formatter), podemos aplicarlo con `git commit --ammend`, se puede sobre escribir el mensaje con `-m`.
### Mutiple commits
Se pueden arreglar el historial de commits con un `git rebase -i [since commit or branch]` y utilizar las estratégias de pick, squash, reword y drop.
En caso de que sepamos que haremos un commit que luego no necesitaremos, podemos hacer:
- `git commit --fixup [commit hash]` -> descarta el commit message de este commit y mantiene el del commit de referencia
- `git commit --squash [commit hash]` -> git juntará los mensajes de todos los commits a hacer squash y el commit de referencia.
Finalmente podemos hacer `git rebase -i --autosquash` y git eligirá las opciones necesarias a tomar en vez de tener que hacerlo de manera manual.
## Revertir cambios
Si necesitamos _"desacer"_ los cambios introducidos en uno o multiples commits, podemos utilizar ˋgit revert --no-edit older_commit_hashˆ..newer_commit_hashˋ, donde:
- git realizará un nuevo commit con los cambios contrarios por cada commit en el rango
- utilizar ˋˆˋ en el ˋold_commit_hashˋ incluirá ese commit en la reversión de cambios, si no se agrega se empezará a revertir de un commit más adelante.
- ˋ--no-editˋ es utilizado para que git no nos pregunte por el message de cada nuevo commit
- primero debe ser el commit más antiguo, porque git creará nuevos commits en orden provisto y de hacerlo al revez aparecerán conflictos
- si solo se quiere revertir un commit, se puede especificar solo ese hash y ya