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 30

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Bueno busque y lo que falta es una coma y un array,resulta que useEffect recibe un segundo parametro llamado: ‘Arreglo 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

, []

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

, [ ]

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:

agregar el segundo argumento

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

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

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 “to 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

Por estar jugando jajja estas clases estan demasiado buenas

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

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’s 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’s 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 “ven 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()

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.

, [ ]

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

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

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