Ας δημιουργήσουμε μια απλή εφαρμογή Todo με το Next.js, η οποία σας διδάσκει τις βασικές αρχές του CRUD (Δημιουργία, ανάγνωση, ενημέρωση και διαγραφή)

Γεια σας παιδιά! Σήμερα, θα δημιουργήσουμε μια απλή εφαρμογή Todo χρησιμοποιώντας το Next.js. Έκανα επίσης ένα άρθρο σχετικά με τη δημιουργία μιας εφαρμογής Todo χρησιμοποιώντας το React, το οποίο όλοι αγαπήσατε! Έτσι, σκέφτηκα να γράψω ένα άρθρο για τη δημιουργία μιας παρόμοιας εφαρμογής Todo, αυτή τη φορά χρησιμοποιώντας το Next.js. Το Next.js είναι ένα πλαίσιο React που επεκτείνει και ενισχύει τις δυνατότητες που προσφέρει το React για να το κάνει πιο ισχυρό τη δημιουργία εφαρμογών για τον Ιστό. Επομένως, εάν δεν είστε εξοικειωμένοι με το Next.js, θα σας δώσω μια σύντομη επισκόπηση του Next.js και των πλεονεκτημάτων του.

Το Next.js είναι ένα πλαίσιο React που παρέχει υβριδική στατική απόδοση & απόδοση διακομιστή και προ-απόδοση διαδρομής. Μερικά από τα βασικά χαρακτηριστικά του Next.js είναι:

  1. Υβριδική στατική απόδοση και απόδοση διακομιστή: Οι σελίδες εκ των προτέρων αποδίδονται σε κάθε αίτημα και εξάγονται ως στατικά αρχεία HTML + JSON για γρήγορη φόρτωση σελίδων σε μελλοντικές επισκέψεις.
  2. Προαπόδοση διαδρομής: Μπορείτε να προ-απόδοσης όλων των σελίδων κατά το χρόνο δημιουργίας. Αυτό επιτρέπει γρήγορη φόρτωση πρώτης σελίδας και βελτιωμένο SEO.
  3. Αυτόματος διαχωρισμός κώδικα: Το Webpack διαχωρίζει δυναμικά πακέτα JS για κάθε διαδρομή, ώστε η εφαρμογή σας να φορτώνει μόνο ό,τι χρειάζεται.
  4. Εύκολη εισαγωγή στοιχείων: Εισαγάγετε φύλλα στυλ, εικόνες και άλλα στοιχεία όπως οι λειτουργικές μονάδες JavaScript.
  5. Υποστήριξη TypeScript: Χρησιμοποιήστε το TypeScript για να δημιουργήσετε την εφαρμογή σας και το Next.js παρέχει ενσωματωμένη υποστήριξη.
  6. Δέχεται κανονικά στοιχεία React: Χρησιμοποιήστε οποιαδήποτε στοιχεία ή βιβλιοθήκες React θέλετε.

Η δημιουργία μιας εφαρμογής Todo είναι εύκολη και δεν απαιτεί πολύ χρόνο, αλλά σας διδάσκει μερικές σημαντικές έννοιες. Σας διδάσκει την αρχή του CRUD (Δημιουργία, Ανάγνωση, Ενημέρωση και Διαγραφή), η οποία είναι πολύ σημαντικό να κατανοήσει οποιοσδήποτε προγραμματιστής.

Δεδομένου ότι αυτό είναι το πρώτο μας έργο στον κόσμο του Next.js, θα κρατούσαμε τα πράγματα απλά. Θα ασχολούμαστε μόνο με το frontend και δεν θα έχουμε καμία βάση δεδομένων ή διακομιστή υποστήριξης. Επίσης, δεν θα χρησιμοποιήσουμε τεχνικές για να διατηρήσουμε τα δεδομένα μεταξύ των περιόδων σύνδεσης με τη βοήθεια cookie ή τοπικής αποθήκευσης, επομένως στην εφαρμογή Next.js, όλα τα δεδομένα θα διαγραφούν μόλις κλείσει ο ιστότοπος.

Δεν είναι ιδανικό σενάριο να χάσουμε τα δεδομένα μετά την ανανέωση σελίδας, αλλά εφόσον μαθαίνουμε το Next.js για πρώτη φορά, η έναρξη με μια απλή εφαρμογή todo θα λειτουργήσει καλύτερα. Αφού κατανοήσετε καλά τις έννοιες, μπορείτε να επεκτείνετε τις γνώσεις για να δημιουργήσετε εφαρμογές εργασίας με μια βάση δεδομένων ή διακομιστή υποστήριξης συνδεδεμένο σε αυτήν ή να δημιουργήσετε ακόμα καλύτερες εφαρμογές. Σχεδιάζω επίσης να γράψω περισσότερα άρθρα στο Next.js και πιθανότατα θα γράψω για τη δημιουργία μιας πιο σύνθετης εφαρμογής Next.js που θα περιλαμβάνει τη χρήση API για αλληλεπίδραση με το backend.

Λοιπόν, ας ξεκινήσουμε τη δημιουργία της εφαρμογής Todo μας:

Ρύθμιση του Έργου

Για να δημιουργήσουμε ένα νέο έργο Next.js, θα εκτελέσουμε τον ακόλουθο κώδικα:

npx create-next-app todo

Χρησιμοποιούμε το npx για να εκτελέσουμε την εντολή create-next-app, η οποία θα δημιουργήσει ένα νέο έργο Next με το όνομα todo για εμάς. Το npx είναι μέρος του Node Package Manager και χρησιμοποιείται για την εγκατάσταση και τη διαχείριση εξαρτήσεων που φιλοξενούνται στο μητρώο npm.

Τώρα, θα πάμε μέσα στο φάκελο todo. Χρησιμοποιήστε την εντολή για να μεταβείτε σε αυτό:

cd todo

Όταν μεταβαίνουμε στον φάκελο todo, μπορούμε να δούμε ορισμένους φακέλους και αρχεία που θα μοιάζουν με αυτό:

Όπως μπορείτε να δείτε, υπάρχουν ορισμένοι φάκελοι όπως node_modules, σελίδες, δημόσιο και στυλ και ορισμένα αρχεία όπως αρχείο next.config.js, αρχείο package.json και αρχείο .gitignore. Λοιπόν, ας καταλάβουμε εν συντομία τι σημαίνει κάθε φάκελος και αρχείο και ποιος είναι ο σκοπός καθενός από αυτά.

  • node_modules: Αυτός ο φάκελος περιέχει όλες τις εξαρτήσεις για την εφαρμογή Next.js. Δεν χρειάζεται να ανησυχούμε πολύ για αυτόν τον φάκελο, καθώς το χειρίζεται η npm για εμάς.
  • pages: Αυτός ο φάκελος είναι όπου θα ορίσουμε τις σελίδες για την εφαρμογή μας. Κάθε αρχείο σε αυτόν τον φάκελο αντιπροσωπεύει μια σελίδα στην εφαρμογή μας και το Next.js δημιουργεί αυτόματα τις διαδρομές για αυτές τις σελίδες. Θα χρησιμοποιήσουμε μόνο index.js για την εφαρμογή Todo μας, αλλά σε πιο σύνθετα έργα με πολλές ιστοσελίδες, θα χρειαστεί να δημιουργήσουμε πολλές σελίδες.
  • public: Αυτός είναι ο φάκελος όπου θα τοποθετήσουμε στατικά στοιχεία όπως εικόνες, γραμματοσειρές και favicon.ico. Δεν θα χρησιμοποιήσουμε αυτόν τον φάκελο στο έργο μας.
  • styles: Αυτός είναι ο φάκελος όπου ορίζουμε τα στυλ CSS για τον ιστότοπο. Θα επεξεργαστούμε το αρχείο globals.css για να συμπεριλάβουμε σχετικό CSS για την εφαρμογή Todo.
  • next.config.js: Αυτό είναι το αρχείο στο οποίο μπορούμε να διαμορφώσουμε το Next.js. Για παράδειγμα, μπορείτε να το χρησιμοποιήσετε για να ρυθμίσετε προσαρμοσμένες διαμορφώσεις πακέτων ιστού ή για να προσθέσετε μεταβλητές περιβάλλοντος, αλλά θα το αφήναμε ανέγγιχτο.
  • package.json: Αυτό είναι το αρχείο όπου ορίζουμε τις εξαρτήσεις και τα σενάρια της εφαρμογής μας. Για παράδειγμα, μπορείτε να το χρησιμοποιήσετε για να προσθέσετε ένα σενάριο για την εκκίνηση του διακομιστή ανάπτυξης ή για τη δημιουργία της εφαρμογής σας για παραγωγή. Επίσης, δεν θα το χρησιμοποιήσουμε στην εφαρμογή Todo.

Θα χρησιμοποιήσουμε μόνο δύο αρχεία για τη δημιουργία της εφαρμογής Todo — index.js από σελίδες και globals.css από στυλ. Επίσης, για καλύτερη κατανόηση του τρόπου λειτουργίας του Next.js, ας ρίξουμε μια ματιά στο αρχείο _app.js μέσα στο φάκελο pages. Μπορεί να θεωρηθεί ως σημείο εισόδου για την αίτησή μας. Δεν χρειάζεται να κάνουμε αλλαγές σε αυτό το αρχείο.

import '../styles/globals.css'

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

Στη συνέχεια, ας γράψουμε έναν κώδικα CSS που θα χρειαστούμε για να δώσουμε ένα βασικό σχέδιο στην εφαρμογή μας. Δεν εστιάζουμε πολύ σε αυτή την πτυχή. Μπορείτε να σχεδιάσετε την εφαρμογή σας σύμφωνα με τις προτιμήσεις σας με όμορφο CSS.

globals.css

Έτσι, όλο το CSS μας θα μπει μέσα σε αυτό το αρχείο μέσα στο φάκελο στυλ.

html,
body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

.container {
  max-width: 800px;
  margin: 2rem auto;
}

.todo-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem;
  background-color: #f0f0f0;
  margin-bottom: 0.5rem;
  border-radius: 5px;
}

.todo-item.done {
  text-decoration: line-through;
  opacity: 0.6;
}

button {
  background-color: transparent;
  border: none;
  cursor: pointer;
}

button.delete {
  color: red;
  margin-left: 1rem;
}

Στη συνέχεια, μεταβαίνουμε στο αρχείο index.js όπου θα γραφεί η κύρια λογική του κώδικά μας.

index.js

Λοιπόν, τώρα θα ξεκινήσουμε με τη δημιουργία της λογικής της εφαρμογής todo μας. Θα ορίσουμε μια λίστα todosjavascript που θα περιέχει όλες τις εργασίες μας. Θα χρησιμοποιήσουμε το setTodosκαι θα χρησιμοποιήσουμε τη βιβλιοθήκη useState που εισάγουμε από το React. Δηλώνουμε επίσης μια συμβολοσειρά input, την οποία θα χρησιμοποιήσουμε για να αποθηκεύσουμε την είσοδο στη νέα φόρμα todo. Θα χρησιμοποιήσουμε ξανά τη βιβλιοθήκη useStateκαι θα ορίσουμε ένα setInput.

import { useState } from "react";

const TodoApp = () => {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");
};

Στη συνέχεια, προχωράμε στο μέρος για την προσθήκη Todos. Θα ορίσουμε μια συνάρτηση addTodo την οποία θα χρησιμοποιήσουμε για να χειριστούμε τη λογική για την προσθήκη ενός νέου Todo. Αυτό θα ενεργοποιείται κάθε φορά που κάποιος χρήστης υποβάλλει μια φόρμα.

const addTodo = (e) => {
    e.preventDefault();
    if (!input) return;
    setTodos([...todos, { id: Date.now(), text: input, done: false }]);
    setInput("");
  };

Επομένως, πρώτα απ 'όλα, θα πρέπει να αποτρέψουμε την προεπιλεγμένη συμπεριφορά της υποβολής φόρμας, που είναι η επαναφόρτωση της σελίδας, καθώς δεν θέλουμε να ανανεωθεί η σελίδα μας κατά την υποβολή της φόρμας. Θέλουμε απλώς να προσθέσουμε αυτήν την εκκρεμότητα και να την εμφανίσουμε στη λίστα εργασιών χωρίς ανανέωση σελίδας.

Στη συνέχεια, έχουμε μια δήλωση if η οποία ελέγχει εάν το πεδίο input είναι κενό. Εάν είναι, η συνάρτηση επιστρέφει και δεν κάνει τίποτα, καθώς δεν μπορούμε να προσθέσουμε ένα κενό todo. Εάν το πεδίο input δεν είναι κενό, θα καλέσουμε τη συνάρτηση setTodos με έναν νέο πίνακα που περιλαμβάνει τον υπάρχοντα πίνακα todos και ένα νέο αντικείμενο που αντιπροσωπεύει το νέο αντικείμενο εργασίας.

Το νέο αντικείμενο θα έχει ένα id που δημιουργείται από τη μέθοδο Date.now() που ορίζει την ημερομηνία στην τρέχουσα ώρα, μια ιδιότητα text στην τρέχουσα τιμή του πεδίου input (το todo) και μια ιδιότητα done που έχει οριστεί σε false που σημαίνει αν η εκκρεμότητα είναι επισημάνθηκε ως ολοκληρωμένο ή όχι. Τέλος, η συνάρτηση setInput καλείται με μια κενή συμβολοσειρά για να καθαρίσει το πεδίο εισαγωγής.

Στη συνέχεια, μεταβαίνουμε στο τμήμα deleteTodo όπου θα χειριστούμε τη διαγραφή των todos.

const deleteTodo = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

Ορίζουμε μια συνάρτηση που ονομάζεται deleteTodo που αφαιρεί ένα αντικείμενο todo από τον πίνακα todos με βάση το id του, το οποίο θα μεταβιβάζουμε στη συνάρτηση κάθε φορά που κάποιος κάνει κλικ στο κουμπί Delete. Αυτό το κάνουμε χρησιμοποιώντας τη μέθοδο filter για να δημιουργήσουμε έναν νέο πίνακα που εξαιρεί το αντικείμενο εργασίας με το καθορισμένο id και στη συνέχεια ενημερώνει την κατάσταση todos με τον νέο πίνακα χρησιμοποιώντας τη συνάρτηση setTodos.

Στη συνέχεια, μεταβαίνουμε στο τμήμα όπου θα ορίσουμε τη συνάρτηση markTodo όπου θα ορίσει τη λογική για την επισήμανση μιας συγκεκριμένης εργασίας ως ολοκληρωμένης.

const markTodo = (id) => {
    setTodos(
      todos.map((todo) => (todo.id === id ? { ...todo, done: !todo.done } : todo))
    );
  };

Θα ορίσουμε μια συνάρτηση που ονομάζεται markTodo που θα εναλλάσσει την ιδιότητα done ενός στοιχείου εκκρεμότητας στον πίνακα todos με βάση το id του που μεταβιβάζεται στη συνάρτηση όταν ένας χρήστης κάνει κλικ στο αντικείμενο εργασίας για να το επισημάνει.

Όταν καλείται το markTodo, ενημερώνει την κατάσταση todos αντιστοιχίζοντας πάνω από τον πίνακα todos και δημιουργώντας έναν νέο πίνακα με ενημερωμένα στοιχεία εργασίας. Για κάθε αντικείμενο εργασίας, θα ελέγξουμε αν η ιδιότητα id του ταιριάζει με την καθορισμένη id. Εάν συμβεί αυτό, θα αλλάξουμε την ιδιότητα done. Εάν δεν ταιριάζει με το καθορισμένο id, απλώς επιστρέφουμε το τρέχον αντικείμενο εργασίας.

Τέλος, θα καλέσουμε τη συνάρτηση setTodos με τον νέο πίνακα ενημερωμένων στοιχείων εργασίας, εναλλάσσοντας ουσιαστικά την ιδιότητα done του στοιχείου εκκρεμότητας με το καθορισμένο id.

Στη συνέχεια, θα εμφανίσουμε τη φόρμα για να προσθέσουμε εργασίες στην εφαρμογή μας και θα εμφανίσουμε επίσης όλες τις εργασίες μαζί με ένα κουμπί διαγραφής.

return (
    <div className="container">
      <h1>Todo App</h1>
      <form onSubmit={addTodo}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Add a new todo"
        />
        <button type="submit">Add Todo</button>
      </form>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id} className={`todo-item ${todo.done ? "done" : ""}`}>
            <span onClick={() => markTodo(todo.id)}>{todo.text}</span>
            <button className="delete" onClick={() => deleteTodo(todo.id)}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );

Ξεκινάμε δημιουργώντας ένα κοντέινερ με μια επικεφαλίδα που εμφανίζει "Todo App". Στη συνέχεια δημιουργούμε μια φόρμα που επιτρέπει στους χρήστες να εισάγουν ένα νέο αντικείμενο.

Η φόρμα περιλαμβάνει ένα πεδίο εισαγωγής που είναι δεσμευμένο στην κατάσταση input χρησιμοποιώντας το χαρακτηριστικό value. Όταν αλλάξει το πεδίο εισαγωγής, ενεργοποιείται το συμβάν onChange και ενημερώνει την κατάσταση input με τη νέα τιμή. Χρησιμοποιούμε setInput για το χειρισμό αυτού του τμήματος.

Όταν υποβάλλεται η φόρμα, καλείται η συνάρτηση addTodo, η οποία προσθέτει το νέο αντικείμενο εργασίας στην κατάσταση todos.

Κάτω από τη φόρμα, θα εμφανίσουμε μια λίστα με στοιχεία εκκρεμότητας χρησιμοποιώντας τη μέθοδο map για επανάληψη στον πίνακα todos. Για κάθε αντικείμενο εργασίας, δημιουργούμε ένα στοιχείο λίστας με ένα μοναδικό χαρακτηριστικό key και μια κλάση που έχει οριστεί σε todo-item.

Το στοιχείο λίστας περιλαμβάνει ένα στοιχείο span με το κείμενο της εργασίας και ένα συμβάν onClick που καλεί τη συνάρτηση markTodo όταν ο χρήστης κάνει κλικ σε αυτό. Περιλαμβάνει επίσης ένα κουμπί διαγραφής με ένα συμβάν onClick που καλεί τη συνάρτηση deleteTodo όταν ο χρήστης κάνει κλικ σε αυτήν.

Στη συνέχεια, εξάγουμε το στοιχείο TodoApp.

export default TodoApp;

Έτσι, με αυτό, ολοκληρώσαμε τη δημιουργία της εφαρμογής Todo μας. Τώρα, ήρθε η ώρα να δοκιμάσουμε την εφαρμογή μας. Επομένως, εκτελέστε την ακόλουθη εντολή για να ξεκινήσετε τον διακομιστή:

npm run dev

Τώρα, μόλις εκτελέσουμε την παραπάνω εντολή, θα ξεκινήσει ένας τοπικός διακομιστής που φιλοξενεί την εφαρμογή μας. Μεταβείτε στη διεύθυνση URL που αναφέρεται εκεί για να δείτε τον ιστότοπο να εκτελείται. Δοκιμάστε να προσθέσετε εργασίες, να τις επισημάνετε ως ολοκληρωμένες και να τις διαγράψετε.

Έτσι, όπως μπορείτε να δείτε, είναι μια βασική έκδοση μιας εφαρμογής Todo, η οποία είναι απλή και εύκολη στην κατασκευή και μπορεί να κατασκευαστεί σε σύντομο χρονικό διάστημα, αλλά σας διδάσκει πολλά πράγματα και για τις τέσσερις βασικές λειτουργίες CRUD που είναι τα δομικά στοιχεία του οποιαδήποτε ιστοσελίδα. Στη συνέχεια, μπορείτε να εφαρμόσετε την ίδια γνώση σε πιο σύνθετα προβλήματα και να δημιουργήσετε καλύτερους ιστότοπους με περισσότερη λειτουργικότητα. Και εγώ θα γράφω περισσότερα άρθρα στο Next.js σύντομα.

Ο πλήρης κωδικός του αρχείου index.js:

import { useState } from "react";

const TodoApp = () => {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");

  const addTodo = (e) => {
    e.preventDefault();
    if (!input) return;
    setTodos([...todos, { id: Date.now(), text: input, done: false }]);
    setInput("");
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  const markTodo = (id) => {
    setTodos(
      todos.map((todo) => (todo.id === id ? { ...todo, done: !todo.done } : todo))
    );
  };

  return (
    <div className="container">
      <h1>Todo App</h1>
      <form onSubmit={addTodo}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Add a new todo"
        />
        <button type="submit">Add Todo</button>
      </form>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id} className={`todo-item ${todo.done ? "done" : ""}`}>
            <span onClick={() => markTodo(todo.id)}>{todo.text}</span>
            <button className="delete" onClick={() => deleteTodo(todo.id)}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoApp;

Ελπίζω σε όλους να σας άρεσε να διαβάζετε αυτό το άρθρο και να μάθετε κάτι σημαντικό. Εάν έχετε οποιεσδήποτε προτάσεις, παρακαλούμε να τις αναφέρετε στα σχόλια. Ελπίζω να έχετε μια όμορφη μέρα.

Μερικά ακόμα άρθρα που πρέπει να διαβάσετε αφού διαβάσετε αυτό:









Περισσότερο περιεχόμενο στο PlainEnglish.io.

Εγγραφείτε στο δωρεάν εβδομαδιαίο ενημερωτικό δελτίο μας. Ακολουθήστε μας στο Twitter, LinkedIn, YouTube και Discord .

Ενδιαφέρεστε να κλιμακώσετε την εκκίνηση του λογισμικού σας; Ρίξτε μια ματιά στο Circuit.