No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Curso de React.js

Curso de React.js

Juan David Castro Gallego

Juan David Castro Gallego

Actualizando estados desde useEffect

20/34
Recursos

Aportes 44

Preguntas 7

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

Bueno busque y lo que falta es una coma y un array,resulta que useEffect recibe un segundo parametro llamado: 鈥楢rreglo de dependecias鈥, este especifica cuando el efecto debe ser ejecutado,es por eso que al querer ejecutarlo una vez solo se deja el array vacio:

 React.useEffect(()=>{
  setTimeout(()=>{
    const localStorageItems = localStorage.getItem(itemName)
    let parsedItem;
      if (!localStorageItems) {
        localStorage.setItem(itemName, JSON.stringify(initialValue));
        parsedItem = initialValue;
      } else {
        parsedItem = JSON.parse(localStorageItems);
        setItem(parsedItem)
      }
      setLoading(false)
  },2000);
  }, [])

Asi quedaria el codigo corregido!!

De esta manera cuando carga no muestra ninguna informaci贸n, as铆 se ve m谩s limpio el dise帽o. Hice un componente loading con un SVG animado para que muestre eso mientras carga. Tambi茅n agregu茅 unas condicionales por que no tiene sentido que muestre el TodoCounter si no hay todos.


return (
    <div className="App">
      {!loading? <>
        <TodoSearch 
          searchValue={searchValue}
          setSearchValue={setSearchValue}
        />  
        {searchedTodos.length===0? <></>: <TodoCounter total={totalTodos} completed={completedTodos}/>}    
          <TodoList>
            {error && <p>We have an error. Refresh please!</p>}
            {!loading && searchedTodos.length===0 && <p>Make your first TODO!</p>}
            {searchedTodos.map(todo=>(
              <TodoItem
              key={todo.text} text={todo.text} completed={todo.completed} onComplete={()=>completeTodos(todo.text)} onDelete={() => deleteTodo(todo.text)}
              />
            ))}
          </TodoList>
          <CreateTodoButton/>
          </>: <Loading/>}
    </div>
  );

hay que colocar 鈥,[]鈥 para que el useEffect no caiga en un bucle infinito,
gracias por las explicaiones JDC eres un crack

Para resolver el ejercicio, solo hay que agregar al used effect un array vacio , [ ] para que no se ejecute automaticamente.

El error del useEffect es que falta el arreglo de dependencias que va como segundo argumento, si no le ponemos ese array vacio en este caso, causara un error algo asi como 鈥渢o many renders鈥

El codigo quedaria algo asi:

useEffect(() => {
    // todo el codigo que esta dentro del useEffect
  }, []);

El aviso que est谩s viendo es una advertencia del linter (en este caso ESLint) sobre el uso del hook useEffect en tu archivo useLocalStorage.js. La advertencia indica que necesitas proporcionar una lista de dependencias para el hook useEffect para evitar una cadena infinita de actualizaciones.

Aqu铆 tienes el c贸digo corregido con la lista de dependencias adecuada en el hook useEffect:

import React from "react";

function useLocalStorage(itemName, initialValue) {
  const [item, setItem] = React.useState(initialValue);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(false);

  React.useEffect(() => {
    try {
      let localStorageItem = localStorage.getItem(itemName);

      let parsedItem;

      if (!localStorageItem) {
        localStorage.setItem(itemName, JSON.stringify(initialValue));
        parsedItem = initialValue;
      } else {
        parsedItem = JSON.parse(localStorageItem);
        setItem(parsedItem);
      }

      setLoading(false);
    } catch (error) {
      setLoading(false);
      setError(true);
    }
  }, [itemName, initialValue]); // Agregar itemName e initialValue como dependencias

  const saveItem = (newItem) => {
    localStorage.setItem(itemName, JSON.stringify(newItem));
    setItem(newItem);
  };

  return { item, saveItem, loading, error };
}

export { useLocalStorage };

En esta versi贸n corregida, he a帽adido [itemName, initialValue] como segundo argumento al hook useEffect, lo que indica a React que debe ejecutar el efecto solamente cuando cambien itemName o initialValue. Esto previene la posibilidad de un ciclo infinito de actualizaciones.
.
By CHATGPT

A mi nunca me dio errores, nunca me habia preocupado de no ver un error .__.

Por estar jugando jajja estas clases estan demasiado buenas

, []

, [ ]

El error es m谩s profundo de lo que parece, curioso que nadie se dio cuenta:

https://github.com/facebook/react/issues/14920

Como comentar贸n compa帽eros, es solo poner:

}, [])

Al final del useEffect 馃槂

Hola Comunidad Platzi! A continuaci贸n les dejo mis apuntes de las 2 煤ltimas clases sobre estados de Carga y Error con un paso a paso de los cambios realizados en nuestros archivos y unos bonus con mi aporte personal, espero les sea de ayuda: https://drive.google.com/file/d/1_eCnRWFm5vbv4JxG57ik-jtRhESCbIMj/view?usp=sharing

Un preview del pdf:

Mis notas de useEffect:
-Efectos de react
React.useEffect(
() => {
guardamos aqu铆 la
parte pesada o demorada
de la aplicaci贸n
},
segundo argumento, ejemplo:
[] array vacio
)

  1. Si no se pasa el segundo argumento
    deja de 煤ltimo lo que est谩 dentro de
    la funci贸n, pero sigue ejecutando.

  2. Si se pasa el arreglo vacio, en el
    primer render ejecuta al igual que el caso 1, pero al causar nuevos renders como escribir en el input nunca se ejecuta de nuevo, solo se ejecuta una vez.

  3. Si pasamos un estado derivado al array, ejemplo, totalTodos, el c贸digo de la funci贸n se ejecuta cada vez que cambia el estado totalTodos.

agregar el segundo argumento

Hace f谩cil la comprensi贸n entre l铆neas de c贸digo, me encanta como explica!

quiero dar mi aporte dejando el c贸digo para puedan entender un poco mejor el flujo de lo que est谩 haciendo el profe en el localStorage

import React from "react";
import { useEffect } from "react";
//custom Hooks
export const useLocalStorage = (itemName, initialValue)=>{
    //local storage
    const item_Todos = () => {
        /**
         * Retrieves the value of an item from the local storage. If the item does not exist, it sets the initial value for the item in the local storage and returns the initial value. If the item exists, it returns the value of the item from the local storage.
         * 
         * @returns {any} The value of the item from the local storage.
         */
        let localStorageItem = JSON.parse(localStorage.getItem(itemName));
        if (!localStorageItem) {
            localStorage.setItem(itemName, JSON.stringify(initialValue));
            return (localStorageItem = initialValue);
        } else {
            return localStorageItem;
        }
    };
    //state of react
    const [item, setItem] = React.useState(initialValue);
    const [loading, setLoading] = React.useState(true);
    const [error, setError] = React.useState(false);
    //useEffect
    useEffect(()=>{
        setTimeout(()=>{
            try {
                setItem(item_Todos());
                setLoading(false);
            } catch (error) {
                setLoading(false);
                setError(true);
            }
        }, 1800);
    },[])

    //almacenamiento en local storage
    const saveItem=(newItem)=>{
        localStorage.setItem(itemName, JSON.stringify(newItem));
        setItem(newItem);
    }
    return {item, saveItem, loading, error}
}

Creo que el error es que hizo falta el [ ].

馃煝 Les comparto este blog sobre el error 'React hook `useEffect` has a missing dependency', <https://kinsta.com/knowledgebase/react-hook-useeffect-has-a-missing-dependency/>

La soluci贸n es colocar. Al final , [ ].

Falto el \[ ] del useEffect
El que faltar谩 el `[]` me estaba dando una crisis, en mis pensamientos dec铆a 鈥淛uan falta el `, []`!鈥 jajajaja

Hola, en mi caso agregue esto: , [itemName, initialValue]); para quitar 1 warning.

import React from "react";

function useLocaStorage(itemName, initialValue) {

  const [item, setItem] = React.useState(initialValue);

  const [loading, setLoading] = React.useState(true);

  const [error, setError] = React.useState(false);

    React.useEffect(() => {
      setTimeout(() => {
        try { 
          const localStorageItem = localStorage.getItem(itemName);
    
          let parsedItem;
      
            if (!localStorageItem) {
              localStorage.setItem(itemName, JSON.stringify(initialValue));
              parsedItem = initialValue;
            } else {
              parsedItem = JSON.parse(localStorageItem);
              setItem(parsedItem);
            }
      
            setLoading(false);
      
        } catch(error) {
          setLoading(false);
          setError(true);
        }
      }, 2000);
    }, [itemName, initialValue]);
  
    const saveItem = (newItem) => {
      localStorage.setItem(itemName, JSON.stringify(newItem));
      
      setItem(newItem);
    };
  
    return {item, 
    saveItem,
    loading,
    error,
    };
  
}

export {useLocaStorage};
Protectores de estado en React: * Nada, siempre se ejecuta el efecto. * \[], el efecto se ejecuta solo una vez. * \[something]: el fecto se ejecuta cada que something se actualiza.

The useEffect hook in React can be used both inside a component and inside a custom hook. However, there are some differences in how they are used and their intended purposes.

When useEffect is used inside a component, it allows you to perform side effects directly within that component. Side effects can include things like fetching data, subscribing to events, or updating the DOM. The useEffect hook inside a component is tied to the lifecycle of that component and will run every time the component is rendered or re-rendered.

On the other hand, when useEffect is used inside a custom hook, it allows you to encapsulate reusable logic and side effects. Custom hooks are a way to share stateful logic between different components without duplicating code. The useEffect hook inside a custom hook is not tied to any specific component鈥檚 lifecycle. Instead, it will be called every time a component that uses the custom hook is rendered or re-rendered.

In summary, when useEffect is used inside a component, it is specific to that component鈥檚 lifecycle. When useEffect is used inside a custom hook, it is reusable and can be used by multiple components. The behavior of useEffect is the same in both cases, but its usage and purpose are different.

Yo lo olvide pero mientras mencionaba que el useEffect seguia siendo infinito recorde que faltaba el array vacio 馃ぃ馃ぃ馃ぃ

React.useEffect(()=>{
    setTimeout(()=>{
      try {
        const localStorageItems = localStorage.getItem(itemName);
        
        let parsedItem;
        
        if (!localStorageItems) {
          localStorage.setItem(itemName,JSON.stringify(initialValue));
          parsedItem = initialValue;
        }else{
          parsedItem = JSON.parse(localStorageItems);
          setItem(parsedItem)
        }
        setLoading(false);
      } catch (error) {
        setLoading(false);
        setError(true);
      }
    }, 2000
    );
  },[]);

jajajajajajajaj 鈥渧en te lo muestro鈥 la cara que hace este tipo es genial jajajajajajajajaja

Hola! este es mi aporte,

React.useEffect(() => {
    try {
      const localStorageItem = localStorage.getItem(itemName)

      let parsedItem

      if (!localStorageItem) {
        localStorage.setItem(itemName, JSON.stringify(initialValue))
        parsedItem = initialValue
      } else {
        parsedItem = JSON.parse(localStorageItem)
        setItem(parsedItem)
      }
      setLoading(false)
    } catch (error) {
      setLoading(false)  
      setError(true)
    }
    // setTimeout(()=>{
      
    // }, 2000)
  }, [])

como pueden ver comente el setTimeout, y el try lo saque y ya no sale el error que renderiza infinitamente

[ ] un array vacio

Le faltan los corechetes al useEffect()

, [ ]

Vi el Video de Nuevo y efectivamente me di cuenta que falto el segundo par谩metro que es un array vac铆o

aqui mi solucion

React.useEffect(() => {
        setTimeout(() => {
            try{
                const localStorageItem = localStorage.getItem(itemName);
            
                let parsedItem;
    
                if(!localStorageItem){
                localStorage.setItem(itemName, JSON.stringify(initialValue));
                parsedItem = initialValue;
                }else {
                parsedItem = JSON.parse(localStorageItem);
                setItem(parsedItem);
                }
    
                setLoading(false);
            } catch (error){
                setLoading(false);
                setError(true);
            }
        }, 2000);
    }, []);

bueno el error esta, en no poner un segundo parametro en el useEffect que seria estos 3 caracteres, 鈥,[ ]鈥 me refiero a un array vacio para que se ejecute una sola vez

*useEffect*(() => { initialize\_item(); }, \[]);
El reto esta en que nuestro useEffect debe contener un estado de loading, ya que es el unico que cambia si se ejecuta la peticion correcta o incorrecta y por tanto solo se ejecutaria 1 sola vez cuando deje de cargar ![](https://static.platzi.com/media/user_upload/image-6595259c-b2a3-447e-afbe-3514e6fe1b6f.jpg)
Yo puse dentro del try un console.log y al ver que se seguia ejecutando esta vez cada dos segundos, puse el segundo parametro del useEffect que se ejecute cuando haya algun cambio en item
Comparto mis apuntes echos en Notion :3 Si tengo errores en los conceptos o t茅rminos que us茅, porfa haganmelo saber ![](https://static.platzi.com/media/user_upload/imagen-d0f4a0e5-e194-45ac-9abc-e584e4405f5f.jpg)
\[]
Como vinos en la clase pasada, falta el Array vacio \[ ] para decirle que solamente se ejecute cuando el array cambia.

Yo hice quiz谩 una pendejada, pero me pareci贸 interesante y es que al recargar la p谩gina, el t铆tulo que contiene el componente TodoCounter dec铆a que ya hab铆a completado los TODOs, de acuerdo a un reto de clases pasadas, pero no era cierto, por lo que use el estado de loading como prop desde el componente para validar si estaba cargando, cambiara el t铆tulo por uno de carga.

Les dejo el c贸digo por si quieres chekearlo.

import './TodoCounter.css'
function TodoCounter({ total, completed, loading }){

    let content;

    if (loading == true){
      content = (<h1 className="TodoCounter">
      Estamos cargando los resultados...
      </h1>
      );

    } else if (total === completed) {
      content = (<h1 className="TodoCounter">
        隆Felicitaciones, completaste todos los TODOs!
        </h1>
      );

      } else {
      
      content = (<h1 className="TodoCounter">
        Has completado <span>{completed}</span> de <span>{total}</span> TODOs
        </h1>
      );
      
      }
      
    return content;
  }

export { TodoCounter };

![](

yo resolveria el problema con un booleano, de que loading = false, luego se mete al bucle y ya lo hago true, y afuera tengo un if, que si es true ya no se cumpla. es una solucion muy floja jajaja xd, tengo sue帽o :p