Saltar al contenido

useEffect – Evita el bucle infinito al actualizar el estado

Después de de esta extensa recopilación de información solucionamos esta problema que suelen tener ciertos usuarios. Te brindamos la solución y esperamos que resulte de gran apoyo.

Solución:

Yo diría que esto significa que hacerlo de esta manera no es lo ideal. De hecho, la función depende de todos. Si setTodos se llama en otro lugar, la función de devolución de llamada debe volver a calcularse, de lo contrario, opera con datos obsoletos.

¿Por qué almacenas los ordenados? array en estado de todos modos? Puedes usar useMemo para ordenar los valores cuando el key o la array cambios:

const sortedTodos = useMemo(() => 
  return Array.from(todos).sort((a, b) => 
    const v1 = a[sortKey].toLowerCase();
    const v2 = b[sortKey].toLowerCase();

    if (v1 < v2) 
      return -1;
    

    if (v1 > v2) 
      return 1;
    

    return 0;
  );
, [sortKey, todos]);

Entonces referencia sortedTodos En todas partes.

Ejemplo en vivo:

const useState, useCallback, useMemo = React;

const exampleToDos = [
    title: "This", priority: "1 - high", text: "Do this",
    title: "That", priority: "1 - high", text: "Do that",
    title: "The Other", priority: "2 - medium", text: "Do the other",
];

function Example() 
    const [sortKey, setSortKey] = useState('title');
    const [todos, setTodos] = useState(exampleToDos);

    const sortedTodos = useMemo(() => 
      return Array.from(todos).sort((a, b) => 
        const v1 = a[sortKey].toLowerCase();
        const v2 = b[sortKey].toLowerCase();

        if (v1 < v2) 
          return -1;
        

        if (v1 > v2) 
          return 1;
        

        return 0;
      );
    , [sortKey, todos]);

    const sortByChange = useCallback(e => 
        setSortKey(e.target.value);
    , []);
    
    return (
        
Sort by:  sortedTodos.map((text, title, priority) => (

title priority

text
))
); ReactDOM.render(, document.getElementById("root"));
body 
    font-family: sans-serif;

.todo 
    border: 1px solid #eee;
    padding: 2px;
    margin: 4px;

.todo h4 
    margin: 2px;

.priority 
    float: right;

No es necesario almacenar los valores ordenados en el estado, ya que siempre puede derivar/calcular los valores ordenados array de la “base” array y el tipo key. Yo diría que también hace que su código sea más fácil de entender ya que es menos complejo.

El motivo del bucle infinito es que todos no coincide con la referencia anterior y el efecto se volverá a ejecutar.

¿Por qué usar un efecto para una acción de clic de todos modos? Puedes ejecutarlo en una función como esta:

const [todos, setTodos] = useState([]);

function sortTodos(e) 
    const sortKey = e.target.value;
    const clonedTodos = [...todos];
    const sorted = clonedTodos.sort((a, b) => 
        return a[sortKey.toLowerCase()].localeCompare(b[sortKey.toLowerCase()]);
    );

    setTodos(sorted);

y en tu menú desplegable haz un onChange.