Home > database >  React rendering previous array state (sorting)
React rendering previous array state (sorting)

Time:09-02

Basically im developing a component where i use the .map method in an array stored in a state and render another component for each occurrence of that array, besides that im making a component that sorts the array according to some parameters using the .sort method

The problem im facing is that my component is rendering the previous state of the array, so if i sort it by a parameter and then sort it by another parameter, the array showing rendered on the screen is the one sorted by the first parameter, just like that:

(likes = sort by highest green number | deslikes = sort by highest red number)

enter image description here

The code:

  • Component rendering the array

export default function Piadas() {
  const [searchBarContent, setSearchBarContent] = useState("");
  const [order, setOrder] = useState("");
  const [jokes, setJokes] = useState([])

  useEffect(() => {
    if(jokes.length == 0)
      fetchData("getJokes");
  }, [jokes])

  function fetchData(url) {
    fetch(`http://localhost:3006/${url}`)
      .then(response => {
        return response.json();
      })
      .then(data => {
        setJokes(data.data);
      });
  }

  
  return (
    <div>
      <Head>
        <title>Só piada boa</title>
        <meta
          name="description"
          content="Aplicação utilizando Banco de dados, CRUD, REST e Next.JS"
        />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <ContainerStageBackgroundPiadas>
          <LightBrownMobileWrapper>
            <UtilsWrapper
              searchBarContent={searchBarContent}
              setSearchBarContent={setSearchBarContent}
              order={order}
              setOrder={setOrder}
              jokes={jokes}
              setJokes={setJokes}
            />
            <CardWrapper>
            
            {
            jokes
            .map((data) => (
              <Card data={data} key={uuidv4()} />
            ))
            }
            </CardWrapper>
          </LightBrownMobileWrapper>
        </ContainerStageBackgroundPiadas>
      </main>
    </div>
  );
}

  • Popover component that orders onChange of the input:

    export default function Popover({order, setOrder, jokes, setJokes}) {
    useEffect(() => {
      if(order === "likes")
        setJokes(jokes.sort((a, b) => (a.likes < b.likes ? 1 : -1)))
      else if(order === "dislikes")
        setJokes(jokes.sort((a, b) => (a.dislikes < b.dislikes ? 1 : -1)))
    
    console.log(jokes);
    }, [order, jokes, setJokes])
    
    return (
      <PopoverContainer style={{width: "100%"}}>
          <PopoverTrigger>
          Ordenar
          </PopoverTrigger>
          <PopoverContent>
              <div>
                  <input type="radio" name="orderRadio" value="likes" onChange={(event) => setOrder(event.target.value)} />
                  <p>Likes</p>
              </div>
              <div>
                  <input type="radio" name="orderRadio" value="dislikes" onChange={(event) => setOrder(event.target.value)} />
                  <p>Deslikes</p>
              </div>
          </PopoverContent>
      </PopoverContainer>
    )
    

    }

CodePudding user response:

I solved the problem by changing the way i was doing the sort, i was changing the state directly and then doing the map on that state, now that state remains with his original value and then i make the .sort directly in his original value on the render, maybe react doenst handle well the first way (sorting the value of the state i was mapping), anyway this looks way better now:

  function sortParams(a, b){
    if(order === "likes"){
      return a.likes < b.likes ? 1 : -1
    }
    else if(order === "dislikes")
      return a.dislikes < b.dislikes ? 1 : -1
  }
  
  return (
    <div>
      <Head>
        <title>Só piada boa</title>
        <meta
          name="description"
          content="Aplicação utilizando Banco de dados, CRUD, REST e Next.JS"
        />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <ContainerStageBackgroundPiadas>
          <LightBrownMobileWrapper>
            <UtilsWrapper
              searchBarContent={searchBarContent}
              setSearchBarContent={setSearchBarContent}
              order={order}
              setOrder={setOrder}
            />
            <CardWrapper>
            {
              jokes
              .sort(sortParams)
              .filter(filterParams)
              .map((data) => (
                <Card data={data} key={uuidv4()} />
              ))
            }
            </CardWrapper>
          </LightBrownMobileWrapper>
        </ContainerStageBackgroundPiadas>
      </main>
    </div>
  );
}

CodePudding user response:

you should remember that sort modify the original values so you could simply get a copy of the jokes by either [...jokes] or jokes.slice()

  • Related