Quest: Obiekt, map i useState

Poniżej jest moje rozwiązanie pierwszego i drugiego punktu zadania. Jest dość przewidywalne. Unikałem skracania kodu, więc powinno być w miarę zrozumiałe. Nowe elementy skomentowałem. Polecam przeanalizowanie kodu i samodzielne dodanie Bootstrapa (punkt 3).

App.jsx

import { WIDOCZKI } from './assets/data';
import { Box } from './components/Box';
import './App.css';
import { useState } from 'react';
import { Ranking } from './components/Ranking';

function App() {
  // tworzę poszerzoneWidoczki jako stan i dodaję tam pole likes
  //
  // operator ...w kopiuje wszystkie pola obiektu w
  // tworzy nowy obiekt
  // nie przenosi referencji do starego obiektu
  const [extWidoczki, setExtWidoczki] = useState(
    WIDOCZKI.map(w => ({
        ...w,
        likes: 0
    }))
  );
  
  // akcja ma za zadanie po prostu powiększyć likes o 1
  // likes jest jednak polem jednego z obiektów w tablicy extWidoczki
  // więc najpierw wybieram właściwy obiekt item.id === id
  // potem tworzę zmodyfikowany obiekt
    const akcja = (id) => {
      setExtWidoczki(items =>
        items.map(item => {
          if (item.id !== id) return item;
          return { ...item, likes: item.likes + 1 };
        })
      );
    };
  return (
    <>
      <div className="grid">
        { extWidoczki.map(item => (
            <Box
              key={item.id}
              nazwa={item.nazwa}
              plik={item.plik}
              opis={item.opis}
              likes={item.likes}
              setLikes={() => akcja(item.id)}
            />
          ))
        }
        <div className="box">
          <h3>Ranking</h3>
          <Ranking data={extWidoczki} />
        </div>
      </div>
    </>
  );
}
export default App;

Ranking.jsx

export function Ranking({data}){
    return (
        <>
        {data
            .slice()
            .sort((a, b) => b.likes - a.likes)
            .map(item => (
                <div key={item.id}>
                {item.nazwa}
                </div>
            ))
            }
        </>
    )
}

// slice() tworzy kopię 
// bo sort() mutuje tablicę, a nie wolno mutować stanu Reacta
//
// (a, b) => b.likes - a.likes to funkcja porównująca

Box.jsx

import './Box.css';

export function Box({ nazwa, plik, opis, likes, setLikes }) {
    return (
        <div className="box">
        <img src={plik} alt={nazwa} />
        <h3>{nazwa}</h3>
        <p>
            {opis} 
            <button onClick={setLikes}>Polub</button> {likes} 
        </p>
        </div>
    );
}

Bootstrapowy szkielet do zadania 3

<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Minimal Bootstrap</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

<div class="container my-4">
  <div class="row g-3">

    <div class="col-12 col-md-6">
      <div class="card p-3">Kafelek 1</div>
    </div>

    <div class="col-12 col-md-6">
      <div class="card p-3">Kafelek 2</div>
    </div>

    <div class="col-12 col-md-6">
      <div class="card p-3">Kafelek 3</div>
    </div>

    <div class="col-12 col-md-6">
      <div class="card p-3">Kafelek 4</div>
    </div>

  </div>
</div>

</body>
</html>

Jedna odpowiedź

Twój komentarz

Zapisz moje dane, adres e-mail i witrynę w przeglądarce aby wypełnić dane podczas pisania kolejnych komentarzy.