Ναι, η React αναλαμβάνει την ανάπτυξη front-end. Το ερώτημα είναι γιατί.

Ενημέρωση: Αυτό το άρθρο είναι πλέον μέρος του βιβλίου μου "React.js Beyond The Basics". Διαβάστε την ενημερωμένη έκδοση αυτού του περιεχομένου και περισσότερα σχετικά με το React στη διεύθυνση jscomplete.com/react-beyond-basics .

Ακολουθούν μερικοί λόγοι για τους οποίους το React έγινε τόσο δημοφιλές τόσο γρήγορα:

  • Η εργασία με το DOM API είναι δύσκολη. Το React ουσιαστικά δίνει στους προγραμματιστές τη δυνατότητα να συνεργάζονται με ένα εικονικό πρόγραμμα περιήγησης που είναι πιο φιλικό από το πραγματικό πρόγραμμα περιήγησης. Το εικονικό πρόγραμμα περιήγησης της React ενεργεί σαν πράκτορας μεταξύ του προγραμματιστή και του πραγματικού προγράμματος περιήγησης.
  • Το React δίνει τη δυνατότητα στους προγραμματιστές να περιγράψουν δηλωτικά τις διεπαφές χρήστη τους και να μοντελοποιήσουν την κατάσταση αυτών των διεπαφών. Αυτό σημαίνει, αντί να καταλήγουν σε βήματα για να περιγράψουν συναλλαγές σε διεπαφές, οι προγραμματιστές απλώς περιγράφουν τις διεπαφές σε όρους τελικής κατάστασης (όπως μια συνάρτηση). Όταν συμβαίνουν συναλλαγές σε αυτήν την κατάσταση, το React φροντίζει να ενημερώσει τις διεπαφές χρήστη βάσει αυτής.
  • Το React είναι απλώς JavaScript, υπάρχει ένα πολύ μικρό API για να μάθετε, μόνο μερικές λειτουργίες και πώς να τα χρησιμοποιήσετε. Μετά από αυτό, οι δεξιότητές σας σε JavaScript είναι που σας κάνουν έναν καλύτερο προγραμματιστή React. Δεν υπάρχουν εμπόδια στην είσοδο. Ένας προγραμματιστής JavaScript μπορεί να γίνει παραγωγικός προγραμματιστής React σε λίγες ώρες.

Αλλά υπάρχουν πολλά περισσότερα από αυτό απλώς. Ας προσπαθήσουμε να καλύψουμε όλους τους λόγους πίσω από την αυξανόμενη δημοτικότητα του React. Ένας λόγος είναι το Virtual DOM (αλγόριθμος συμφιλίωσης του React). Θα εργαστούμε μέσω ενός παραδείγματος για να δείξουμε την πραγματική πρακτική αξία της ύπαρξης ενός τέτοιου αλγορίθμου στην εντολή σας.

Ο επίσημος ορισμός του React αναφέρει ότι πρόκειται για βιβλιοθήκη JavaScript για τη δημιουργία διεπαφών χρήστη . Είναι σημαντικό να κατανοήσετε τα δύο διαφορετικά μέρη αυτού του ορισμού:

  1. Το React είναι μια βιβλιοθήκη JavaScript . Δεν είναι ένα πλαίσιο. Δεν είναι μια ολοκληρωμένη λύση και συχνά θα πρέπει να χρησιμοποιήσουμε περισσότερες βιβλιοθήκες με το React για να σχηματίσουμε οποιαδήποτε λύση. Το React δεν αναλαμβάνει τίποτα για τα άλλα μέρη σε οποιαδήποτε πλήρη λύση. Επικεντρώνεται σε ένα μόνο πράγμα, και στο να κάνει αυτό το πράγμα πολύ καλά.
  2. Αυτό που κάνει πολύ καλά το React είναι το δεύτερο μέρος του ορισμού: δημιουργία διεπαφών χρήστη . Η διεπαφή χρήστη είναι οτιδήποτε βάζουμε μπροστά στους χρήστες για να αλληλεπιδρούν με έναν υπολογιστή. Οι διεπαφές χρήστη είναι παντού, από τα απλά κουμπιά ενός φούρνου μικροκυμάτων έως τον ταμπλό ενός διαστημικού λεωφορείου. Εάν η συσκευή που προσπαθούμε να διεπαφή μπορεί να κατανοήσει τη JavaScript, μπορούμε να χρησιμοποιήσουμε το React για να περιγράψουμε μια διεπαφή χρήστη για αυτήν.

Δεδομένου ότι τα προγράμματα περιήγησης στο Web κατανοούν τη JavaScript, μπορούμε να χρησιμοποιήσουμε το React για να περιγράψουμε τις διεπαφές χρήστη Ιστού. Μου αρέσει να χρησιμοποιώ τη λέξη περιγράφει εδώ γιατί αυτό είναι που εμείς ουσιαστικά να κάνει με React, εμείς απλά θα πω αυτό που θέλουμε και React θα κατασκευάσει την πραγματική διεπαφές χρήστη, εκ μέρους μας, στο πρόγραμμα περιήγησης στο Web. Χωρίς React ή παρόμοιες βιβλιοθήκες, θα πρέπει να δημιουργήσουμε χειροκίνητα περιβάλλοντα χρήστη με εγγενή API Ιστού και JavaScript.

Όταν ακούτε τη δήλωση ότι "Το React είναι δηλωτικό", αυτό ακριβώς σημαίνει, περιγράφουμε τις διεπαφές χρήστη με το React και το λέμε τι θέλουμε (όχι πώς να το κάνουμε). Το React θα φροντίσει για το "πώς" και θα μεταφράσει τις περιγραφικές μας δηλώσεις (τις οποίες γράφουμε στη γλώσσα React) σε πραγματικές διεπαφές χρήστη στο πρόγραμμα περιήγησης. Το React μοιράζεται αυτήν την απλή δηλωτική ισχύ με το ίδιο το HTML, αλλά με το React, πρέπει να είμαστε δηλωτικοί για διεπαφές HTML που αντιπροσωπεύουν δυναμικά δεδομένα, όχι μόνο στατικά δεδομένα.

Το React έχει τρεις βασικές έννοιες σχεδιασμού που οδηγούν στη δημοτικότητά του:

1 - Η χρήση επαναχρησιμοποιήσιμων, συνθέσιμων και συστατικών στοιχείων

Στο React, περιγράφουμε διεπαφές χρήστη χρησιμοποιώντας στοιχεία. Μπορείτε να σκεφτείτε στοιχεία ως απλές λειτουργίες (σε οποιαδήποτε γλώσσα προγραμματισμού). Καλούμε συναρτήσεις με κάποια είσοδο και μας δίνουν κάποια έξοδο. Μπορούμε να επαναχρησιμοποιήσουμε τις λειτουργίες όπως απαιτείται και να συνθέσουμε μεγαλύτερες λειτουργίες από μικρότερες.

Τα στοιχεία είναι ακριβώς τα ίδια. ονομάζουμε την εισαγωγή τους «ιδιότητες» και «κατάσταση» και μια έξοδος συστατικού είναι μια περιγραφή ενός περιβάλλοντος εργασίας χρήστη (το οποίο είναι παρόμοιο με το HTML για προγράμματα περιήγησης). Μπορούμε να επαναχρησιμοποιήσουμε ένα στοιχείο σε πολλαπλές διεπαφές χρήστη και τα στοιχεία μπορούν να περιέχουν άλλα στοιχεία.

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

2 - Η φύση των αντιδραστικών ενημερώσεων

Το όνομα του React είναι η απλή εξήγηση για αυτήν την ιδέα. Όταν αλλάζει η κατάσταση ενός στοιχείου (η είσοδος), αλλάζει επίσης η διεπαφή χρήστη που αντιπροσωπεύει (η έξοδος). Αυτή η αλλαγή στην περιγραφή του περιβάλλοντος εργασίας χρήστη πρέπει να αντικατοπτρίζεται στη συσκευή με την οποία εργαζόμαστε.

Σε ένα πρόγραμμα περιήγησης, πρέπει να αναδημιουργήσουμε τις προβολές HTML στο Document Object Model (DOM). Με το React, δεν χρειάζεται να ανησυχούμε για το πώς θα αντικατοπτρίζουμε αυτές τις αλλαγές ή ακόμη και να διαχειριστούμε πότε θα πραγματοποιήσουμε αλλαγές στο πρόγραμμα περιήγησης. Το React απλώς θα αντιδρά στις αλλαγές της κατάστασης και θα ενημερώνει αυτόματα το DOM όταν χρειάζεται.

3 - Η εικονική αναπαράσταση των προβολών στη μνήμη

Με το React, γράφουμε HTML χρησιμοποιώντας JavaScript. Βασιζόμαστε στη δύναμη του JavaScript για τη δημιουργία HTML που εξαρτάται από ορισμένα δεδομένα, αντί να βελτιώσουμε το HTML ώστε να λειτουργεί με αυτά τα δεδομένα. Η βελτίωση της HTML είναι αυτό που συνήθως κάνουν τα άλλα πλαίσια JavaScript. Για παράδειγμα, το Angular επεκτείνει HTML με δυνατότητες όπως βρόχους, υπό όρους και άλλα.

Όταν λαμβάνουμε μόνο τα δεδομένα από το διακομιστή (στο παρασκήνιο, με AJAX), χρειαζόμαστε κάτι περισσότερο από HTML για να δουλέψουμε με αυτά τα δεδομένα. Χρησιμοποιεί είτε ένα βελτιωμένο HTML είτε χρησιμοποιεί τη δύναμη του JavaScript για τη δημιουργία του HTML. Και οι δύο προσεγγίσεις έχουν πλεονεκτήματα και μειονεκτήματα. Το React αγκαλιάζει το τελευταίο, με το επιχείρημα ότι τα πλεονεκτήματα είναι ισχυρότερα από τα μειονεκτήματα.

Στην πραγματικότητα, υπάρχει ένα σημαντικό πλεονέκτημα που μπορεί να κάνει το ίδιο για αυτήν την προσέγγιση. Η χρήση JavaScript για την απόδοση HTML διευκολύνει το React να διατηρεί μια εικονική αναπαράσταση του HTML στη μνήμη (η οποία είναι συνήθως γνωστή ως The Virtual DOM ). Το React χρησιμοποιεί το εικονικό DOM για να αποδώσει ένα δέντρο HTML ουσιαστικά πρώτα και στη συνέχεια, κάθε φορά που αλλάζει μια κατάσταση και λαμβάνουμε ένα νέο δέντρο HTML που πρέπει να μεταφερθεί στο DOM του προγράμματος περιήγησης, αντί να γράψει ολόκληρο το δέντρο δεν θα γράφει μόνο το διαφορά μεταξύ του νέου δέντρου και του προηγούμενου δέντρου (αφού το React έχει στη μνήμη και τα δύο δέντρα). Αυτή η διαδικασία είναι γνωστή ως Tree Reconciliation και νομίζω ότι είναι το καλύτερο πράγμα που έχει συμβεί στην ανάπτυξη ιστοσελίδων από το AJAX!

Στο ακόλουθο παράδειγμα, θα επικεντρωθούμε σε αυτήν την τελευταία ιδέα και θα δούμε ένα απλό πρακτικό παράδειγμα της διαδικασίας συμφιλίωσης δέντρων και τη μεγάλη διαφορά που κάνει. Θα γράψουμε το ίδιο παράδειγμα HTML δύο φορές, πρώτα χρησιμοποιώντας εγγενή API Ιστού και βανίλια JavaScript και στη συνέχεια θα δούμε πώς να περιγράψουμε το ίδιο δέντρο HTML με το React.

Για να επικεντρωθούμε καθαρά σε αυτήν την τελευταία ιδέα, δεν θα χρησιμοποιούμε στοιχεία και θα χλευάσουμε μια λειτουργία αλλαγής κατάστασης χρησιμοποιώντας ένα χρονόμετρο JavaScript. Επίσης, δεν πρόκειται να χρησιμοποιήσουμε το JSX, αν και η χρήση του JSX θα δημιουργήσει έναν πολύ απλούστερο κώδικα. Χρησιμοποιώ το JSX όλη την ώρα όταν γράφω το React, αλλά η εργασία με το React API απευθείας σε αυτό το παράδειγμα θα σας κάνει ελπίζω να καταλάβετε αυτήν την ιδέα πολύ καλύτερα.

Παράδειγμα αλγορίθμου συμφιλίωσης του React

Για να ακολουθήσετε αυτό το παράδειγμα, χρειάζεστε ένα πρόγραμμα περιήγησης και έναν επεξεργαστή κώδικα. Μπορείτε πραγματικά να χρησιμοποιήσετε μια διαδικτυακή παιδική χαρά κωδικοποίησης, αλλά θα χρησιμοποιήσω τοπικά αρχεία και θα τα δοκιμάσω απευθείας σε ένα πρόγραμμα περιήγησης (δεν χρειαζόμαστε διακομιστή ιστού):

Θα ξεκινήσουμε αυτό το παράδειγμα από το μηδέν. Δημιουργήστε έναν νέο κατάλογο και ξεκινήστε τον αγαπημένο σας επεξεργαστή εκεί:

mkdir react-democd react-demoatom .

Δημιουργήστε ένα index.htmlαρχείο σε αυτόν τον κατάλογο και τοποθετήστε ένα τυπικό πρότυπο HTML εκεί. Συμπεριλάβετε σε αυτό το πρότυπο ένα script.jsαρχείο και τοποθετήστε μια console.logδήλωση σε αυτό το σενάριο για να ελέγξετε ότι η συμπερίληψη λειτουργεί:

    React Demo     

Ανοίξτε το index.htmlαρχείο στο πρόγραμμα περιήγησής σας και βεβαιωθείτε ότι μπορείτε να δείτε το κενό πρότυπο χωρίς προβλήματα και ότι μπορείτε να δείτε στην καρτέλα Dev-Tools της κονσόλας το console.logδοκιμαστικό μήνυμα που βάλατε script.js:

open index.html # On Mac explorer index.html # On Windows

Now, let’s bring in the React library itself, which we can include from the Reactjs website. Copy both the react and react-dom scripts, and include them in index.html:

We’re including two different scripts here for an important reason: The React library itself can be used without a browser. To use React with a browser, we need the ReactDOM library.

When we refresh the browser now, we should see both React and ReactDOM available on the global scope:

With this simple setup, we can now access both React and ReactDOM APIs, and of course, we also have access to the native Web APIs and JavaScript which we are going to use first.

To insert HTML dynamically in the browser we can simply use pure JavaScript and the DOM Web API itself. Let’s create a div element to host our JavaScript HTML content and give it the id "js". In the body element of index.html, right before the script tag, add:

Now in script.js, let's grab this new div element by its id and put it in a constant. Let's name this constant jsContainer. We can use document.getElementById to grab the div from HTML:

jsContainer.innerHTML = ` Hello JS `;

To control the content of this div, we can use the innerHTML setter call on the div element directly. We can use this call to supply any HTML template that we want inserted in the DOM. Let's insert a div element with a class of "demo" and the string "Hello JS" as its content:

jsContainer.innerHTML = ` Hello JS `;ReactDOM.render( /* TODO: React's version of the HTML template */, reactContainer )

Make sure this works in the browser. You should see the “Hello JS” line on the screen now.

This demo div is our User Interface so far. It’s a very simple one. We just output a text for the user to see.

Both document.getElementById and element.innerHTML are actually part of the native DOM Web API. We are communicating with the browser directly here using the supported APIs of the Web platform. When we write React code, however, we use the React API instead, and we let React communicate with the browser using the DOM Web API.

React acts like our agent for the browser, and we mostly need to communicate with just React, our agent, and not the browser itself. I say mostly because there are cases where we still need to communicate with the browser, but those are rare.

To create the exact same User Interface that we have so far but with React API this time, let’s create another div element and give it an id of "react". In index.html, right under the div#js element, add:

Now, in script.js, create a new container constant for the new div:

const reactContainer = document.getElementById("react");

This container will be the only call we make to the native web API. ReactDOM needs this container to know where to host our application in the DOM.

With the react container identified, we can now use the ReactDOM library to render React's version of the HTML template to this container:

ReactDOM.render( /* TODO: React's version of the HTML template */, reactContainer )

What we’re going to do next is your first milestone in truly understanding the React library. Remember when I told you that with React we write HTML using JavaScript? This is exactly what we are going to do next.

To write our simple HTML User Interface, we are going to use JavaScript calls to React API, and by the end of the example you’ll have a better picture about the reason for doing so.

Instead of working with strings (as we did in the native JavaScript example above), in React, we work with objects. Any HTML string will be represented as an object using a React.createElement call (which is the core function in the React API).

Here’s the equivalent HTML User Interface we have so far with React:

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React" ), reactContainer );

React.createElement has many arguments:

  • The first argument is the HTML tag, which is div in our example.
  • The second argument is an object that represents any attributes we want this tag to have. To match the native JS example we used { className: "demo" } which translates to class="demo". Note how we used className instead of class in the attributes because with React it's all JavaScript that matches the Web API, not HTML itself.
  • The third argument is the content of the element. We’ve put a “Hello React” string in there.

We can test this now. The browser should render both “Hello JS” and “Hello React”. Let’s style the demo divs as a box, using this CSS, just so that we can visually split the screen. In index.html:

 .demo { border: 1px solid #ccc; margin: 1em; padding: 1em; } 

We now have two nodes, one being controlled with the DOM Web API directly, and another being controlled with the React API (which in turn uses the DOM Web API). The only major difference between the ways we are building these two nodes in the browser is that in the JS version we used a string to represent the content, while in the React version we used pure JavaScript calls and represented the content with an object instead of a string.

No matter how complicated the HTML User Interface is going to get, when using React, every HTML element will be represented with a JavaScript object using a React.createElement call.

Let’s now add some more features to our simple User Interface. Let’s add a text box to read input from the user.

To nest elements in our HTML template, it’s straight forward in the JS version because it’s just HTML. For example, to make the demo div render an element, we simply add it to the content:

jsContainer.innerHTML = ` Hello JS `;

We can do the same with React by adding more arguments after the 3rd argument for React.createElement. To match what we did in the native JS example, we can add a 4th argument that is another React.createElement call that renders an input element (remember, every HTML element is an object):

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React", React.createElement("input") ), reactContainer );

At this point, if you’re questioning what we’re doing and thinking “this is complicating a simple process”, you are totally right! But there is a very good reason for what we’re doing. Keep reading.

Let’s also render a timestamp in both versions. In the JS version, let’s put the timestamp in a paragraph element. We can use a call to new Date() to display a simple timestamp:

jsContainer.innerHTML = ` Hello JS  

${new Date()}

`;

To do the same in React, we add a 5th argument to the top-level div element. This new 5th argument is another React.createElement call, this time using a p tag, with no attributes, and the new Date() string for content:

ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React", React.createElement("input"), React.createElement( "p", null, new Date().toString() ) ), reactContainer );

Both JS and React versions are still rendering the exact same HTML in the browser.

As you can see, so far, using React is actually a lot harder than the simple and familiar native way. What is it that React does so well that’s worth giving up the familiar HTML and having to learn a new API to write what can be simply written in HTML? The answer is not about rendering the first HTML view, it’s about what we need to do to update any existing view in the DOM.

So, let’s do an update operation on the DOM we have so far. Let’s simply make the timestamp tick every second.

We can easily repeat a JavaScript function call in a browser using the setInterval Web timer API. So, let's put all of our DOM manipulations for both JS and React versions in a function, call it render, and use it in a setInterval call to make it repeat every second.

Here’s the full final code in script.js:

const jsContainer = document.getElementById("js"); const reactContainer = document.getElementById("react"); const render = () => { jsContainer.innerHTML = ` Hello JS  

${new Date()}

`; ReactDOM.render( React.createElement( "div", { className: "demo" }, "Hello React ", React.createElement("input"), React.createElement( "p", null, new Date().toString() ) ), reactContainer ); } setInterval(render, 1000);

When we refresh the browser now, the timestamp string should be ticking every second in both versions. We are now updating our User Interface in the DOM.

This is the moment when React will potentially blow your mind. If you try to type something in the text box of the JS version, you won’t be able to. This is very much expected because we’re basically throwing away the whole DOM node on every tick and regenerating it. However, if you try to type something in the text box that’s rendered with React, you can certainly do so!

Although the whole React rendering code is within our ticking timer, React is changing only the timestamp paragraph and not the whole DOM node. This is why the text input box was not regenerated and we were able to type in it.

You can see the different ways we’re updating the DOM visually if you inspect the two DOM nodes in a Chrome dev tools elements panel. The Chrome div tools highlights any HTML elements that get updated. You’ll see how we are regenerating the whole “js” div on every tick, while React is smartly only regenerating the paragraph with the timestamp string.

React has a smart diffing algorithm that it uses to only regenerate in its DOM node what actually needs to be regenerated while it keeps everything else as is. This diffing process is possible because of React’s virtual DOM and the fact that we have a representation of our User Interface in memory (because we wrote in JavaScript).

Using the virtual DOM, React keeps the last DOM version in memory and when it has a new DOM version to take to the browser, that new DOM version will also be in memory, so React can compute the difference between the new and the old versions (in our case, the difference is the timestamp paragraph).

React will then instruct the browser to update only the computed diff and not the whole DOM node. No matter how many times we regenerate our interface, React will take to the browser only the new “partial” updates.

Όχι μόνο αυτή η μέθοδος είναι πολύ πιο αποτελεσματική, αλλά αφαιρεί επίσης ένα μεγάλο επίπεδο πολυπλοκότητας για τον τρόπο που σκεφτόμαστε την ενημέρωση των διεπαφών χρήστη. Έχοντας το React κάνουμε όλους τους υπολογισμούς σχετικά με το αν πρέπει να ενημερώσουμε το DOM ή όχι, μας δίνει τη δυνατότητα να επικεντρωθούμε στη σκέψη για τα δεδομένα μας (κατάσταση) και τον τρόπο περιγραφής ενός περιβάλλοντος εργασίας χρήστη για αυτό.

Στη συνέχεια διαχειριζόμαστε τις ενημερώσεις στα δεδομένα μας όπως απαιτείται χωρίς να ανησυχούμε για τα βήματα που απαιτούνται για να αντικατοπτρίσουμε αυτές τις ενημερώσεις στο πραγματικό περιβάλλον εργασίας χρήστη στο πρόγραμμα περιήγησης (επειδή γνωρίζουμε ότι το React θα κάνει ακριβώς αυτό και θα το κάνει με αποτελεσματικό τρόπο!)

Ευχαριστώ για την ανάγνωση! Μπορείτε να δείτε τον πηγαίο κώδικα του demo μου εδώ και μπορείτε να δείτε το demo να τρέχει εδώ.

Εκμάθηση αντίδρασης ή κόμβος; Δείτε τα βιβλία μου:

  • Μάθετε το React.js δημιουργώντας παιχνίδια
  • Node.js Πέρα από τα βασικά