skip to Main Content

I tried with React to iterate through an Iterator with some manipulations and I have found one myself with the wrapper useReducer, but I would like to know if it exists a simpler solution than this one :

function reducer(state, action) {
        // eslint-disable-next-line default-case
        switch (action.type) {
            case 'update' : {
                return { payload : action.payload, pokemon : action.payload.next().value }
            }
            case 'changePokemon' : {

                const actualPokemon = state.payload.next().value
                return {...state, pokemon : actualPokemon}
            }
        }
    }

    const [state, dispatch] = useReducer(reducer, {pokemon : []})



    useEffect(  () => {
        fetch("/missionDay").then(res => {
            res.json().then(r => dispatch({type : 'update', payload : r.message.map(id => Pokemon.find(pok => pok.id === id)).values()})).catch(r => console.log(r))
        })
    }, [])

3

Answers


  1. Yes, there are several simpler ways to iterate over an Iterator in JavaScript and React.

    Using a spread operator (simplest for one-time conversion):

    const iterator = someArray.values();
    const allValues = [...iterator]; // Converts iterator to array
    

    Using Array.from():

    const iterator = someArray.values();
    const allValues = Array.from(iterator);
    

    For React specifically, if you need to maintain state and update it, you could use useState with one of the above methods:

    const [pokemons, setPokemons] = useState([]);
    
    useEffect(() => {
      fetch("/missionDay")
        .then(res => res.json())
        .then(r => {
          const pokemonIterator = r.message
            .map(id => Pokemon.find(pok => pok.id === id))
            .values();
          setPokemons([...pokemonIterator]);
        })
        .catch(console.log);
    }, []);
    

    If you need to iterate one by one, you can use a for…of loop:

    const iterator = someArray.values();
    for (const value of iterator) {
      // do something with value
    }
    

    If you specifically need to maintain the iterator state and move through it one at a time in React, you could use useState with the next() method:

    const [iterator, setIterator] = useState(null);
    const [currentPokemon, setCurrentPokemon] = useState(null);
    
    const moveToNext = () => {
      const result = iterator.next();
      if (!result.done) {
        setCurrentPokemon(result.value);
      }
    };
    
    useEffect(() => {
      fetch("/missionDay")
        .then(res => res.json())
        .then(r => {
          const pokemonIterator = r.message
            .map(id => Pokemon.find(pok => pok.id === id))
            .values();
          setIterator(pokemonIterator);
          setCurrentPokemon(pokemonIterator.next().value);
        })
        .catch(console.log);
    }, []);
    

    Your useReducer approach works but might be overcomplicated for this use case. Unless you need complex state management or have specific requirements for maintaining the iterator state, one of the simpler approaches above would be more straightforward.

    Login or Signup to reply.
  2. Yes, skilled are various more natural habits to emphasize over an Iterator in JavaScript and React.Using a spread driver (plainest for previous conversion):

    const iterator = someArray.values(); 
    const allValues = [...iterator];
    

    If you need to repeat one at a time, you can use a for…of loop:
    const iterator = someArray.values();

    for (const value of iterator) {
    // do entity with value
     }
    

    If you expressly need to claim the iterator state and move through it individually in React, you keep use useState accompanying the next() arrangement:

    import { useState, useEffect } from 'react'
    

    const [iterator, setIterator] = useState(null)
    const [currentPokemon, setCurrentPokemon] = useState(null)

    const moveToNext = () => {
    if (iterator) {
    const { done, value } = iterator.next();
    if (done !== 'true') {
      setCurrentPokemon(value);
    }
    }
    }
    
    useEffect(() => {
    const fetchPokemon = async()=>{
    try {
    const response = await fetch("/missionDay");
    if (!response.ok) throw new Error('Network response was not ok');
    const data = await response.json();
    const pokemonIterator = data.message
    .map(id => Pokemon.find(pok => pok.id == id))
    .values() 
    setIterator(pokemonIterator);
    setCurrentPokemon(pokemonIterator.next().value); 
    }
    catch (e) {
    console.error('Failed to fetch data:', e);
    }
    }
    fetchPokemon();
    },[]);
    export default moveToNext;
    
    Login or Signup to reply.
  3. Always, Keep in mind that an iterator (in JavaScript) is simply any object that follows the iterator protocol: it has a .next() method that returns items in a sequence until it’s done. The tricky part is that you can’t use array methods like .map() or .forEach() directly on iterators—these methods work on arrays (or array-like structures).

    How to iterate over an iterator?
    To iterate over an iterator more “naturally” in JavaScript, you can either:

    Spread it into an array:

    js

        const arrayFromIterator = [...myIterator];
    
        arrayFromIterator.map(...)
        arrayFromIterator.forEach(...)
       // Use a for...of loop:
    
    
        for (const item of myIterator) {
           console.log(item);
              }

    Once you convert or iterate it in a loop, you have the resulting items in a typical JavaScript data structure (e.g., an array) that’s easily consumed by React or other libraries.

    For your react code :

    function MyComponent() {
      const [pokemons, setPokemons] = React.useState([]);
    
      React.useEffect(() => {
        fetch("/missionDay")
          .then((res) => res.json())
          .then((data) => {
            // data.message is presumably an array of IDs
            // Convert them to the actual Pokemon array
            const fetchedPokemons = data.message.map((id) =>
              Pokemon.find((pok) => pok.id === id)
            );
            setPokemons(fetchedPokemons); // store as array
          })
          .catch((err) => console.error(err));
      }, []);
    
      // Then render it easily in the JSX:
      return (
        <ul>
          {pokemons.map((pokemon) => (
            <li key={pokemon.id}>{pokemon.name}</li>
          ))}
        </ul>
      );
    }

    Upvote if helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search