A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Custom Hook para Local Storage

14/23
Recursos

Aportes 21

Preguntas 10

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

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

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";

Para crear un custom hook es necesario:

  1. definir el lugar donde se guardar谩 la variable,
  2. implementar una funcion que se encargue de actualizar el valor de la variable.
  3. RETORNAR la variable y la funcion en forma de array!

Los custom hook SIEMPRE deben comenzar por la palabra use ejemplo useLocalStorage, y como es una funcion, debe recibir m铆nimo 2 par谩metros:

  1. El nombre de lo que buscar谩, o crear谩, y
  2. el estado inicial de la variable(puede ser un objeto {}, un array [], un string vac铆o 鈥溾, etc)

En este sitio tenemos unos cuantos hooks ya creados

useHooks

Y aca tenemos el de localStorage
LocalStorage

Cual seria la diferencia entre un React Hook y una funci贸n normal? por el momento las veo iguales.

De tanto cambia cambia de nombres ahora todo me da error. 馃槪

Recuerden:
Siempre podemos crear nuestros propios Hooks siempre y cuando se compla esta condicion: Debe empezar con use

Yo dividi mi custom Hook en una carpeta aparte y asi quedo:

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

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];
}

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;
  1. Yo necesito de todos para calcular su longitud entonces lo pido鈥 const totalTodos = todos.length;
  2. todos, esta en un elemento de react el cual se basa en tener a los todos actuales, tanto como almacenar nuevos todos: [todos, saveTodos]
  3. pero ojo, estos estan unidos a mi hook que cree yo con 2 datos iniciales: = useLocalStorage('TODOS_V1', []);
  4. estos dos van a llamar a mi funcion: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:

  1. Necesitamos de 2 datos iniciales, mi data actual y mi nueva data:[todos, saveTodos]
  2. (鈥楾ODOS_V1鈥, []); estos son algunos parametros pueden haber mas o menos
  3. El uso de mi data(todos) y el retorno de esta ya modificada(item) gracias a lo que hara en un futuro el cambio de estado de en cuyoCaso (saveTodos):
const saveItem = (newItem) => {
    const stringifiedItem = JSON.stringify(newItem)
    localStorage.setItem(itemName,stringifiedItem)
    setItem(newItem)
   }

   return [
     item,
     saveItem,
   ];

Nuestro Custom Hook

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 stringifyItem = JSON.stringify(newItem);
    localStorage.setItem(itemName, stringifyItem);
    setItem(newItem);
  }

  return [item, saveItem];
}

que profe simpatico! y encima saben un monton. best profe in the world

Fernando鈥

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

C贸digo de la clase:

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];
}

custom hook

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 stringifiedTodos = JSON.stringify(newItem);
    localStorage.setItem(itemName, stringifiedTodos);
    setItem(newItem);
  };
  return [item, saveItem];
}

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 鈥渋ntroducci贸n a React鈥.

Al mismo tiempo, los cambios de nombre que meti贸 por todos lados, por favor. Este video fue una pesadilla.

Video q hay q darle replay

Juan David > Alvaro Felipe