Custom Hook para Local Storage
Clase 14 de 23 • Curso de React 17
Contenido del curso
Clase 14 de 23 • Curso de React 17
Contenido del curso
Gonzalo Vidal
Luís Hernández
Sebastian Moreno Olivera
Xamir E Rojas
Reinaldo Mendoza
Rodrigo Ramos Xochiteotzin
Yancarlo Urdaneta
Reinaldo Mendoza
Willy Emanuel Antunez Gonzales
Seba Cardoso
Ingenea SRL
Luis Sánchez M
David Castellanos Zayas
Libian María Hernández Gil
Fredy Daniel Flores Lemus
Juan Castro
Fredy Daniel Flores Lemus
Dimas Antonio Mendoza Lozano
Joaquin Segovia
Nicolas Vezzali Dussio
Luis Fernando Rodriguez Boett
Jhoana España Urresty
Eduardo Diaz
Carlos Andrés Pupiales Córdoba
Jairo Campos Ruiz
Jairo Campos Ruiz
Germán Arevalo Jerez
Damián Gastón Barera Lorenzo
Carlos Andrés Pupiales Córdoba
Luis Lozada
Elías Aguilar
Elías Aguilar
Alejandro Ivan Mendieta
rodrigo roque
Ariel Ezequiel Biazzo Genua
Angel David Contreras Barrios
Gustavo Gonzalez Montero
Juan Castro
Gabriel Hernández Valdez
Héctor Eduardo López Carballo
Juan Castro
Irungaray Agustin
Jherom Chacon
Julio Hidalgo Jara
Juan Castro
El shortcut para seleccionar todas las palabras iguales sin seleccionar una por una, es: dar click sobre la palabra (localStorageItem) y luego Ctrl+Shift+L
Presiona F2 y verás... 😎
Excelente lo del f2
Creo que se debería crear una carpeta para los custom hooks e importarlos en el componente que se usa como en el caso de react, así el proyecto es más modular.
// Custom Hooks import { useLocalStorage } from "../../customHooks/useLocalStorage";
Buena idea
Agree
Para crear un custom hook es necesario:
Los custom hook SIEMPRE deben comenzar por la palabra use ejemplo useLocalStorage, y como es una funcion, debe recibir mínimo 2 parámetros:
Gracias por el resumen
Excelente tu comentario, muchas gracias por la info
En este sitio tenemos unos cuantos hooks ya creados
useHooks
Y aca tenemos el de localStorage LocalStorage
Gracias Seba! gran aporte!
Muy útil las páginas. Gracias!
De tanto cambia cambia de nombres ahora todo me da error. 😣
Los cambios hay que hacerlos con sumo cuidado, y para eso es muy útil usar el atajo con Ctrol+Shift+L. Pero, no se rindan... insistan en conseguir el error... eso es parte del aprendizaje.... A mi me ha costado bastante, pero voy paso a paso, no me permito avanzar sin haber resuelto lo anterior.
Cual seria la diferencia entre un React Hook y una función normal? por el momento las veo iguales.
Los cambios dentro de los React Hooks le avisan a React que debe hacer un nuevo render del componente. Los cambios de una función normal no lo harían eso. :D
Ya entendí, gracias 😊. Por cierto, excelente curso ⭐️⭐️⭐️⭐️⭐️
Yo dividi mi custom Hook en una carpeta aparte y asi quedo:
Hay que hacer un par de cambios pero pude y quedo mucho mas organizado...
Gracias por el aporte! Habia olvidado el export al final del hook y me estaba volviendo loco jaja
Recuerden: Siempre podemos crear nuestros propios Hooks siempre y cuando se compla esta condicion: Debe empezar con use
Tantos nombres y cambios confunden un poco y es algo tedioso ... se debería contemplar esto desde el inicio del proyecto
Es una de las fallas de este profesor, pese a que es muy bueno explicando, cambia todo a ultimo minuto en varios de sus cursos, o usa muchas variables, parametros, argumentos parecidos que confunden.
Muy deacuerdo, son fastidiosos esos cambios.
Yo estoy haciendo el proyecto en TypeScript por si os sirve de ayuda os dejo como hice el hook con Optional Types.
import { useState } from "react"; export function useLocalStorage <A>(itemName: string, initialState:A): [A, (newItems: A) => void ] { const localStorageItem = localStorage.getItem(itemName); let parsedItems: A; if (!localStorageItem) { localStorage.setItem(itemName, JSON.stringify([])); parsedItems = initialState; } else { parsedItems = JSON.parse(localStorageItem); } const [items, setItems] = useState(parsedItems); const saveItems = (newItems: A) => { setItems(newItems); const stringifiedItems = JSON.stringify(newItems); localStorage.setItem(itemName, stringifiedItems); }; return [items, saveItems]; }
Luego para llamar al hook en mi caso lo saque a otro archivo, lo importo y le paso el tipo en el operador diamante <> de esta manera se queda reutilizable.
const [todos, saveTodos] = useLocalStorage <Todo[]>('TODOS_V1', []);
Todo como tal es un type que creamos
export type Todo = { text: string; completed: boolean };
Les recomiendo mucho TypeScript si tienen oportunidad apréndanlo se ahorran mucho errores tonto que cometemos con JavaScript por despiste y a mi me sirve también para reforzar mucho mas lo aprendido.
Gracias, fue de mucha ayuda
Podría ser posible a futuro ser mas puntual con lo que se quiere enseñar? Comprendo tu emoción por querer transmitir todo lo que sabes, pero en tu afán de querer compartirlo todo, terminas yéndote por las ramas.
Lo que estaría bueno es que tengas el código que ténes que escribir ensayado de antemano, de manera que lo que escribas, sea lo que se quede ahí hasta el final del curso.
Si...ya se...en los trabajos no sucede así. Pero acá estamos aprendiendo, es un curso de introducción a React, necesito tener firme lo que me enseñan sin que sufra modificaciones cada 2x3.
No se los demás, todo bien con ellos y sus opiniones...pero a estas alturas lo único que quiero es terminar con esto, que la app funcione y con este código inicializar una propia adaptando lo que aprendí acá a mi propia app.
No quiero sonar mal pero...a veces te sigo y a veces no. Me voy a tener que ir al canal de fazt o de bluuweb por cuarta vez a ver si ahí puedo ver esto desde otro ángulo.
De acuerdo
Madre mía solo se tenia que poner use... para que React lo valide como un custom hook y yo haciendo cosas muy locas para que todo funcione, esto disminuye la complejidad de mi código. Donde has estado toda mi vida Platzi xd
Me parece extraño que hablemos de Hooks de manera tan avanzada, creando uno, sin haberse explayado antes... En otros lados/ bootcamps les dedican hasta 2 clases de más de 2hs cada una al tema de Hooks.
Entiendo que al profesor le resulte fácil el tema (es un genio prodigio, lo acepto), pero eso no significa que deba tomar los temas tan a la ligera. A veces siento que necesitan un reminder que llamaron al curso "introducción a React".
Al mismo tiempo, los cambios de nombre que metió por todos lados, por favor. Este video fue una pesadilla.
Perdón mandé el comentario antes de que terminara el video. Lo de "patito" y "Fernando" me parece un bochorno.
De hecho, solo es una introducción, si no estoy mal, más adelante hay un curso entero sobre este tema de los hooks.
que profe simpatico! y encima saben un monton. best profe in the world
Custom Hook para Local Storage:
Una de las primeras reglas al usar customHooks es que empiecen por use ej: usePatito
Cuando hacemos un customHook, no hacemos el react.usePatito, sino que lo ponemos de una, como si fuera una funcion:
const [bla,bla] = usePatito()
Lo interesante de los customhooks es que no devuleven solo un return o un item, sino mas biem devuelven todo lo que este ahi adentro, todo eso, lo pueden devolver!
Dentro de nuestros customHooks podemos llavar a los reactHooks oficiales
y asi se veria toda la app cambiada con el nuevo local storage y el nuevo hook:
const defaultItem = [ {text: 'Cortar ceboolla', completed: false}, {text: 'Cortar mate con limon', completed: false}, {text: 'Escuchar a devrockkk', completed: false} ] function useLocalStorage(itemName,initalValue) { const localStorageItem = localStorage.getItem(itemName); let parsedItem; //Este if sirve para ver si el usuario entra por primera vez o no y ya hay datos guardadtos en localStorage... if(!localStorageItem) { localStorage.setItem(itemName,JSON.stringify(initalValue)); parsedItem = initalValue; } else { parsedItem = JSON.parse(localStorageItem) } const [item, setItem] = React.useState(parsedItem) const saveItem = (newItem) => { const stringifiedItem = JSON.stringify(newItem) localStorage.setItem(itemName,stringifiedItem) setItem(newItem) } return [ item, saveItem, ]; //se devuelve el array porque asi es la estructura base de reacthooks } function App() { //Fijate como ahora el todos,saveTodos trabajan con 2 parametros diferentes en la funcion localStorage const [todos, saveTodos] = useLocalStorage('TODOS_V1', []); const [searchValue, setSearchValue] = React.useState(''); const completedTodos = todos.filter(todo => !!todo.completed).length; const totalTodos = todos.length; let searchedTodos = []; if (!searchValue.length >= 1) { searchedTodos = todos; } else { searchedTodos = todos.filter(todo => { const todoText = todo.text.toLowerCase(); const searchText = searchValue.toLowerCase(); return todoText.includes(searchText); }); } const completeTodo = (text) => { const todoIndex = todos.findIndex(todo => todo.text === text); const newTodos = [...todos]; newTodos[todoIndex].completed = true; saveTodos(newTodos); }; const deleteTodo = (text) => { const todoIndex = todos.findIndex(todo => todo.text === text); const newTodos = [...todos]; newTodos.splice(todoIndex, 1); saveTodos(newTodos); }; return [ <p>{patito}</p>, <AppUI totalTodos={totalTodos} completedTodos={completedTodos} searchValue={searchValue} setSearchValue={setSearchValue} searchedTodos={searchedTodos} completeTodo={completeTodo} deleteTodo={deleteTodo} />, ]; } export default App;
Las cookies son información que se comparte entre navegador y servidor para compartir información (por ejemplo, de autenticación). LocalStorage en cambio solo vive en el navegador y nos permite guardar información (por nada del mundo cosas relacionadas a autenticación).
Dato interesante:
El custom hook useLocalStorage (en este punto del curso) retorna un array, en el cuál el primer elemento del array es el estado, y el segundo pues es la función que no modifica (por nombrarla así). entonces si yo llamo a la función useLocalStorage y la ejecuto (porque como ves esta utilizando parentesis) esto me retorna ese array:
const myArr = useLocalStorage('TODOS_V1', [])
En ES6 tenemos algo que se llama Destructuring o desestructuración, que nos permite desempacar valores de arreglos o propiedades de objetos en distintas variables.¿para que esto?
pues para ahorrarnos las siguientes lineas de codigo:
const myArr = useLocalStorage('TODOS_V1', []) const item = myArr[0] const saveItem = myArr[1]
Entonces con Desestructuración podemos hacer eso en una sola línea:
const [item, saveItem] = useLocalStorage('TODOS_V1', [])
Algo que debes tener en cuenta es que la destructuring de arrays nos permite darle el nombre que queremos de una a la variable segun la posición que tenga en el array. Lo que en destructuring de objetos no, estos deben tener el mismo nombre, por eso se llaman nombrados.
Dato interesante 2:
Siempre es buena idea tener los custom hooks separados en archivos independientes, a veces incluso creando una carpeta hooks/ donde los guardan todos.
Ahora veamos mas de cerca esta complejidad:
Para explicar esto, toamre solo la data que me importe
function useLocalStorage(itemName,initalValue) { const localStorageItem = localStorage.getItem(itemName); let parsedItem; //Este if sirve para ver si el usuario entra por primera vez o no y ya hay datos guardadtos en localStorage... if(!localStorageItem) { localStorage.setItem(itemName,JSON.stringify(initalValue)); parsedItem = initalValue; } else { parsedItem = JSON.parse(localStorageItem) } const [item, setItem] = React.useState(parsedItem) //el (parsedItem es el elemento que se ha guardado en el localStorage, por eso lo usamos como elemento por defecto con useState, y este mismo, es decir, todos los elementos que el usaurio puede ver porque el los manipulo, son los que exportamos como item, const saveItem = (newItem) => { const stringifiedItem = JSON.stringify(newItem) localStorage.setItem(itemName,stringifiedItem) setItem(newItem) } return [ item, saveItem, ]; //se devuelve el array porque asi es la estructura base de reacthooks }
const [todos, saveTodos] = useLocalStorage('TODOS_V1', []); const totalTodos = todos.length;
const totalTodos = todos.length;[todos, saveTodos]useLocalStorage('TODOS_V1', []);useLocalStorage. Van a probocar 2 cosas, 1) el almacenamiento de la informacion en el localstorage y 2 van a llegar a trabajar con los todos!!! como? con el const [todos, saveTodos] donde el todos, es la informacion que ha yentgo y saveTodos es la informacion nueva que yo desee cargar al hacer ej:const completeTodo = (text) => { const todoIndex = todos.findIndex(todo => todo.text === text); const newTodos = [...todos]; newTodos[todoIndex].completed = true; **saveTodos(newTodos);** };
pero... y como es la funcion que trabaja con saveTodos? esta! mira:
**const saveItem = (newItem) => {** const stringifiedItem = JSON.stringify(newItem) localStorage.setItem(itemName,stringifiedItem) setItem(newItem) }
Por lo tanto... saveItem=saveTodos, es decir, no es igual pero saveTodos necesita de saveItems para que funcione la nueva actualizacion de datos!
5.Ahora, como despues de todo esto yo quiero seguir trabajando con todos, como hago para trabajar con estos? bien, la respuesat des sencilla, luego de operara con la data en localstorage ej: const [item, setItem] = React.useState(parsedItem) necesito que me la devuelva, entonces:
return [ item, saveItem, ];
Asi... item conecta con todos, y saveItem conecta con saveTodos!
Gracias a esto... en conclusion, podemos decir que al crear un hook, trabajremos de la siguiente forma:
const saveItem = (newItem) => { const stringifiedItem = JSON.stringify(newItem) localStorage.setItem(itemName,stringifiedItem) setItem(newItem) } return [ item, saveItem, ];
En esta clase me confundí un poco pero con este video, ya todo me queda mas claro. . https://www.youtube.com/watch?v=xutmKvLsbKM
El Local Storage son las cookies?
Nop, es algo distinto. Las cookies son información que se comparte entre navegador y servidor para compartir información (por ejemplo, de autenticación). LocalStorage en cambio solo vive en el navegador y nos permite guardar información (por nada del mundo cosas relacionadas a autenticación).
Algo no me queda del todo claro, por que al llamar en los métodos para guardar y borrar: saveTodos(newTodos), pero no existe esta función. Veo que se definido cuando se llama al custom hook cuando se definen las propiedades con saveItem: saveTodos , en este caso ¿lo que estamos haciendo es decir que el nuevo nombre del método saveTodos para este llamado seria saveItem? Esto por que al llamar a la funcion se hace con saveTodos(newTodos)
Hola!
La función useLocalStorage prácticamente crea una nueva función con las variables local modificadas. Entonces almacenamos esa función en memoria con el nombre saveTodos en la línea que hacemos const [todos, saveTodos] = useLocalStorage('TODOS_V1', [] ).
Esta función es
const saveTodos = (newItem) => { const stringifiedItem = JSON.stringify(newItem); localStorage.setItem('TODOS_V1', stringifiedItem); setItem(newItem); };
Si te das cuenta solo cambia el primer argumento de la línea 3 localStorage.setItem('TODOS_V1'...). Por esto es que saveItem != saveTodos. Esto son closures, te recomiendo tomar el Curso de Closures y Scope en JavaScript para más info.
¡Exactamente! Tu deducción es correcta, haciendo saveItem: saveTodos estamos cambiándole el nombre a nuestra función. Te recomiendo repasar este tema de destructuring en el Curso de ECMAScript 6+. :wink:
Lo ideal es crear una carpeta hooks para nuestros custom hooks, y dentro, nuestro useLocalStorage.js:
import { useState } from "react"; function useLocalStorage(itemName, initialValue) { const localStorageItem = localStorage.getItem(itemName); let parsedItem; if (!localStorageItem) { localStorage.setItem(itemName, JSON.stringify(initialValue)); parsedItem = initialValue; } else { parsedItem = JSON.parse(localStorageItem); } const [item, setItem] = React.useState(parsedItem); const saveItem = (newItem) => { const stringifiedItem = JSON.stringify(newItem); localStorage.setItem(itemName, stringifiedItem); setItem(newItem); }; return [ item, saveItem, ]; } export { useLocalStorage }
Luego lo importamos de la siguiente manera:
import { useLocalStorage } from "../../hooks/useLocalStorage"; // o donde sea que lo hayamos guardado
Si, esto me gustó
Tantos cambios de nombres y cosas , tengo errores ahora por todos lados sin entender mucho...me sale se esperaba una declaración o una instrucción...?
Si nos muestras tu código, puedo ayudarte con los errores.