Implementazione di schermate di scheletro in reazione

Pubblicato: 2022-03-10
Riepilogo rapido ↬ In questo tutorial imparerai cos'è un'interfaccia utente dello schermo scheletro e alcuni tipi di librerie dello schermo scheletro, insieme ai loro pro e contro. Costruiremo un'interfaccia utente dello schermo scheletro simile a YouTube utilizzando React Loading Skeleton. Quindi, puoi sperimentare da solo con il pacchetto React dello schermo scheletro di tua scelta.

Spinner e caricatori sono stati tradizionalmente il modo per dire agli utenti che il caricamento dei contenuti richiederà un po' di tempo. Sebbene questo approccio sia ottimo, sta rapidamente diventando obsoleto nello sviluppo moderno. Gli schermi Skeleton stanno diventando il sostituto perfetto per i caricatori tradizionali perché si concentrano sui progressi piuttosto che sui tempi di attesa, riducendo così la frustrazione dei tempi di caricamento.

In questo articolo, non analizzeremo le basi della sintassi CSS React o JavaScript, quindi non devi essere un esperto in nessuno di questi linguaggi per seguire.

La differenza tra un caricatore e un'interfaccia utente dello schermo scheletro
La differenza tra un caricatore e un'interfaccia utente dello schermo scheletro (anteprima grande)

Gli esperti di UI e UX ci insegnano che, mentre gli utenti aspettano che i contenuti vengano caricati su una pagina, dovremmo tenerli coinvolti.

L'idea alla base dell'utilizzo degli spinner per coinvolgere gli utenti prima del caricamento dei contenuti è ottima; tuttavia, il risultato può essere tutt'altro che ideale perché la maggior parte degli utenti si annoierà a fissare uno spinner animato fittizio come se fosse un orologio. Luke Wroblewski elabora questo.

Gli schermi Skeleton offrono una migliore esperienza utente riducendo la frustrazione del tempo di caricamento. Concentrandosi sui progressi anziché sui tempi di attesa, crea l'illusione per gli utenti che le informazioni verranno visualizzate in modo incrementale sullo schermo. Bill Chung nella sua ricerca lo conferma.

Che cos'è uno schermo scheletro?

Uno schermo scheletro è una versione dell'interfaccia utente che non contiene contenuto effettivo; imita invece il layout della pagina mostrando i suoi elementi in una forma simile al contenuto reale mentre viene caricato e diventa disponibile (cioè quando la latenza di rete lo consente).

Uno schermo scheletro è essenzialmente un wireframe della pagina, con caselle segnaposto per testo e immagini.

Altro dopo il salto! Continua a leggere sotto ↓

Cosa c'è di unico in uno schermo scheletro?

Un'interfaccia utente scheletrica assomiglia all'interfaccia utente effettiva della pagina, quindi gli utenti capiranno quanto velocemente verrà caricato il Web o l'app mobile anche prima che il contenuto venga visualizzato. Ecco un paio di motivi per cui potresti prendere in considerazione l'utilizzo di schermi scheletrici nel tuo prossimo progetto:

  • imitare il layout di una pagina è più facile con uno schermo scheletro,
  • i contenuti vengono caricati progressivamente (non tutti in una volta).

Gli schermi di scheletro sono anche indicati come:

  • elementi fantasma,
  • segnaposto di contenuto,
  • caricatori di contenuti.

Blockchain.com, YouTube, Facebook, Medium e altre grandi aziende tecnologiche mostrano schermi scheletrici mentre i loro contenuti vengono caricati per migliorare l'esperienza utente.

Blockchain.com

Interfaccia utente dello scheletro di Blockchain.com
Stato di caricamento parziale di Blockchain.com (notare come viene utilizzato uno scheletro nell'analisi del grafico) (Anteprima grande)

medio

Interfaccia utente con schermo a scheletro medio
Interfaccia utente dello scheletro di Medium (Anteprima grande)

LinkedIn

Interfaccia utente della schermata dello scheletro di LinkedIn
Stato di caricamento del feed home di LinkedIn nel 2018 (anteprima grande)

Tipi di schermi scheletrici

Esistono diversi tipi di schermi scheletrici. I principali sono segnaposto di testo e segnaposto di immagine (o colore).

La maggior parte degli sviluppatori preferisce utilizzare i segnaposto di testo come l'interfaccia utente dello scheletro nelle proprie pagine perché sono facili da creare e lo sviluppatore non richiede alcun dettaglio sulla sostanza del contenuto effettivo; invece lo scheletro imita l'interfaccia utente.

I segnaposto colorati sono più difficili da creare perché richiedono dettagli sul contenuto.

Alcuni pacchetti popolari semplificano l'implementazione di schermate scheletriche nelle app Web. Diamo un'occhiata più da vicino a entrambi:

  • Segnaposto di reazione
  • Scheletro di caricamento di reazione

Esamineremo i pro ei contro di ciascun pacchetto, prima di considerare quale utilizzare per la nostra applicazione.

Segnaposto di reazione

Professionisti

  • I componenti segnaposto vengono utilizzati per creare un'interfaccia utente di scheletro personalizzata.
  • È supportata l'animazione a impulsi (cioè l'effetto di movimento su un elemento).
  • Viene fornito con un'API basata su componenti.

contro

  • I componenti dello scheletro vengono gestiti separatamente, quindi l'aggiornamento degli stili di un componente potrebbe richiedere l'aggiornamento anche del componente dello scheletro.
  • La curva di apprendimento non è lineare perché ci sono più componenti per esigenze diverse.

Quello che segue è un esempio di un componente scheletro che utilizza il pacchetto react-placeholder :

 import { TextBlock, RectShape } from 'react-placeholder/lib/placeholders'; import ReactPlaceholder from 'react-placeholder'; const GhostPlaceholder = () => ( <div className='my-placeholder'> <RectShape color='gray' style={{width: 25, height: 70}} /> <TextBlock rows={6} color='blue'/> </div> ); <ReactPlaceholder ready={ready} customPlaceholder={<GhostPlaceholder />}> <MyComponent /> </ReactPlaceholder>

Importando TextBlock e RectShape da react-placeholder/lib/placeholder e ReactPlaceholder da react-placeholder , abbiamo creato un componente funzionale chiamato GhostPlaceholder . GhostPlaceholder ha un div e all'interno del div abbiamo utilizzato il componente RectShape, che descrive le dimensioni di un rettangolo, passa il valore di qualsiasi colore e definisce gli stili del rettangolo.

Successivamente, abbiamo utilizzato il componente TextBlock per impostare i valori per le righe e il colore. Il componente TextBlock definisce il numero di righe e il colore del testo.

Passiamo MyComponent come figlio del componente ReactPlaceholder , che riceve ready e il componente GhostPlaceholder come valori per le sue props ready e customPlaceholder .

Il MyComponent verrà caricato quando viene mostrata l'interfaccia utente della schermata dello scheletro.

Per saperne di più, consulta la documentazione.

Scheletro di caricamento di reazione

Professionisti

  • È basato su API e ha un componente con prop per tutte le personalizzazioni.
  • Può essere utilizzato come componente dello scheletro separato e anche direttamente all'interno di qualsiasi componente, quindi è flessibile.
  • Supporta temi e animazione Pulse.

contro

  • È facile da implementare per un'interfaccia utente di scheletro semplice, ma complicato per scheletri più complessi.
  • Avere un componente scheletro separato renderà più difficile la manutenzione quando l'interfaccia utente e gli stili cambiano.

Quello che segue è un esempio di React Loading Skeleton:

 import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; const SkeletonComponent = () => ( <SkeletonTheme color="#202020" highlightColor="#444"> <section> <Skeleton height={50} width={50} /> </section> </SkeletonTheme> );

Abbiamo importato Skeleton e SkeletonTheme dalla libreria react-loading-skeleton , quindi abbiamo creato un componente funzionale che esegue il rendering del componente SkeletonTheme , con color e hightlightColor come proprietà.

Il componente SkeletonTheme viene utilizzato per la creazione di temi (ad esempio, l'aggiunta di effetti di colore all'interfaccia utente dello scheletro).

Infine, all'interno della sezione, definiamo il componente Skeleton , con le proprietà di altezza e larghezza e i relativi valori passati.

Creazione di un'interfaccia utente dello schermo scheletro simile a YouTube

Creiamo una schermata dello scheletro simile a YouTube, utilizzando React Loading Skeleton, per mostrare come funziona un'interfaccia utente dello scheletro.

Imposta Reagire

Il modo più semplice per configurare React è utilizzare Create React App, che è "un modo ufficialmente supportato per creare applicazioni React a pagina singola. Offre una configurazione di build moderna senza alcuna configurazione.

Lo useremo per avviare l'applicazione che creeremo. Dal tuo terminale, esegui il comando seguente:

 npx create-react-app skeleton-screens && cd skeleton-screens

Una volta completata l'installazione, avviare il server React eseguendo npm start :

App React - App React Scaffold
Pagina di benvenuto di React (Anteprima grande)

Crea l'interfaccia utente di YouTube senza uno schermo scheletro

Innanzitutto, inseriamo i dati fittizi di YouTube. Gli endpoint reali verrebbero normalmente utilizzati al posto dei dati fittizi, ma in questo tutorial utilizzeremo dati fittizi.

Crea un file nella tua cartella src/ e data.js , aggiungi il codice seguente.

 const dummyData= [ { section: "Recommended", channel: "CNN", items: [ { id: "fDObf2AeAP4", image: "https://img.youtube.com/vi/fDObf2AeAP4/maxresdefault.jpg", title: "75 million Americans ordered to stay home", views: "1.9M views", published: "3 days agos" }, { id: "3AzIgAa0Cm8", image: "https://img.youtube.com/vi/3AzIgAa0Cm8/maxresdefault.jpg", title: "Gupta: The truth about using chloroquine to fight coronavirus pandemic", views: "128K views", published: "4 hours ago" }, { id: "92B37aXykYw", image: "https://img.youtube.com/vi/92B37aXykYw/maxresdefault.jpg", title: "Willie Jones STUNS Simon Cowell In Pitch Perfect Performance of 'Your Man'!", views: "2.47 million views", published: "1 month ago" }, { id: "J6rVaFzOEP8", image: "https://img.youtube.com/vi/J6rVaFzOEP8/maxresdefault.jpg", title: "Guide To Becoming A Self-Taught Software Developer", views: "104K views", published: "17 days ago" }, { id: "Wbk8ZrfU3EM", image: "https://img.youtube.com/vi/Wbk8ZrfU3EM/maxresdefault.jpg", title: "Tom Hanks and Rita Wilson test positive for coronavirus", views: "600k views", published: "1 week ago" }, { id: "ikHpFgKJax8", image: "https://img.youtube.com/vi/ikHpFgKJax8/maxresdefault.jpg", title: "Faces Of Africa- The Jerry Rawlings story", views: "2.3 million views", published: "2014" } ] }, { section: "Breaking News", channel: "CGTN America", items: [ { id: "tRLDPy1A8pI", image: "https://img.youtube.com/vi/tRLDPy1A8pI/maxresdefault.jpg", title: "Is Trump blaming China for COVID-19? You decide.", views: "876k views", published: "9 days ago" }, { id: "2ulH1R9hlG8", image: "https://img.youtube.com/vi/2ulH1R9hlG8/maxresdefault.jpg", title: "Journalist still goes to office during pandemic, see her daily routine", views: "873 views", published: "3 hours ago" }, { id: "TkfQ9MaIgU", image: "https://img.youtube.com/vi/_TkfQ9MaIgU/maxresdefault.jpg", title: "How are small businesses going to survive the economic downturn of the COVID-19 era?", views: "283 views", published: "4 day ago" } ] } ]; export default dummyData;

Per replicare il formato di YouTube, abbiamo creato dati fittizi con una serie di oggetti, con proprietà come ID, immagine, titolo, numero di visualizzazioni e data di pubblicazione.

Quindi, creiamo la nostra interfaccia utente di YouTube. Avremo tre componenti:

Card Contiene i dettagli della miniatura, del titolo, del numero di visualizzazioni, della data di pubblicazione e del canale del video.
CardList Restituisce tutte le carte di seguito.
App Monta il nostro oggetto dummyData , carica l'interfaccia utente dello scheletro per due secondi e restituisce il componente CardList .

All'interno della tua cartella src , crea una cartella e chiamala components . All'interno della cartella dei components , crea un file Card.js , aggiungi il seguente codice:

 import React from "react"; const Card = ({ item, channel }) => { return ( <li className="card"> <a href={`https://www.youtube.com/watch?v=${item.id}`} target="_blank" rel="noopener noreferrer" className="card-link" > <img src={item.image} alt={item.title} className="card-image" /> <img src={item.image} alt={item.title} className="channel-image" /> <h4 className="card-title">{item.title}</h4> <p className="card-channel"> <i>{channel}</i> </p> <div className="card-metrics"> {item.views} • {item.published} </div> </a> </li> ); }; export default Card;

Abbiamo creato un componente Card . Al suo interno, abbiamo importato React da react e abbiamo decostruito l' item e channel oggetti di scena in modo che possano essere utilizzati attraverso il componente Card . Ciascun componente dell'elemento della Card che visualizza un video mostrerà la miniatura, il numero di visualizzazioni, la data di pubblicazione e il titolo.

Componente Elenco Carte

All'interno della cartella dei components , crea un file CardList.js e aggiungi il seguente codice:

 import React from "react"; import Card from "./Card"; const CardList = ({ list }) => { return ( <ul className="list"> {list.items.map((item, index) => { return <Card key={index} item={item} channel={list.channel} />; })} </ul> ); }; export default CardList;

In questo componente, abbiamo importato il componente Card che abbiamo creato. La carta accetta gli item di scena e gli oggetti di scena, che list.items channel Quindi esportiamo questo componente come CardList , perché lo utilizzeremo nel nostro componente App .

Nota : l'array di elementi mappato in questo componente è l'array di oggetti nel nostro dummyData .

Componente dell'app

All'interno del file app.js nella directory src/ , elimina il codice presente e aggiungi quanto segue.

 import React, { useState, useEffect } from "react"; import "./App.css"; import dummyData from "./data"; import CardList from "./components/CardList"; const App = () => { const [videos, setVideos] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { setLoading(true); const timer = setTimeout(() => { setVideos(dummyData); setLoading(false); }, 5000); return () => clearTimeout(timer); }, []); return ( <div className="App"> { videos.map((list, index) => { return ( <section key={index}> <h2 className="section-title">{list.section}</h2> <CardList list={list} /> <hr /> </section> ); })} </div> ); }; export default App;

In questo componente, abbiamo importato gli useState e useEffect insieme a React e agli altri file che abbiamo creato e che saranno necessari nel componente App .

Poiché i nostri dati sono dati fittizi, dobbiamo simularli come i dati API caricando il contenuto dopo un timeout di due secondi, utilizzando il metodo JavaScript setTimeout .

Successivamente, nel componente App , creiamo uno stato video e impostiamo lo stato su un array vuoto usando useState .

Per caricare i nostri dati fittizi, useremo l'hook useEffect . Nel nostro hook creiamo un timer variabile che contiene la funzione setTimeout () . All'interno della funzione, impostiamo il nostro stato video sul nostro oggetto dummyData e ci assicuriamo che i dati vengano caricati dopo due secondi e, infine, annulliamo il timer durante lo smontaggio.

Infine, mappiamo attraverso il nostro stato video e restituiamo l'elemento della sezione che contiene la list-section e il componente CardList con i suoi oggetti di scena.

Aggiunta CSS

Fino ad ora, abbiamo usato molte classi senza un vero CSS. All'interno della cartella src , elimina tutto in App.css e sostituiscilo con il seguente codice;

 .App { max-width: 960px; margin: 0 auto; font-size: 16px; } .list { display: flex; justify-content: space-between; flex-wrap: wrap; list-style: none; padding: 0; } .section-title { margin-top: 30px; } .card { width: calc(33% - 10px); margin: 20px 0; } .card-link { color: inherit; text-decoration: none; } .card-image { width: 100%; } .channel-image { border-radius: 100%; padding: 0, 10px, 0, 0; width: 40px; height: 40px; } .card-title { margin-top: 10px; margin-bottom: 0; } .card-channel { margin-top: 5px; margin-bottom: 5px; font-size: 14px; } /* Tablets */ @media (max-width: 1000px) { .App { max-width: 600px; } .card { width: calc(50% - 22px); } } /* Mobiles \*/ @media (max-width: 640px) { .App { max-width: 100%; padding: 0 15px; } .card { width: 100%; } }

Vediamo come appare la nostra interfaccia utente di YouTube senza lo schermo dello scheletro. Puoi vedere che quando la pagina viene caricata, viene visualizzata una schermata bianca per due secondi, quindi i dati vengono caricati prontamente.

Interfaccia utente simile a YouTube senza schermo scheletro
Interfaccia utente simile a YouTube senza schermo scheletro (anteprima grande)

Utilizzo dello scheletro di caricamento di React

A differenza di altre librerie in cui creeresti meticolosamente uno schermo scheletro per abbinare le dimensioni dei caratteri, l'altezza delle linee e i margini del tuo contenuto, il componente Skeleton è progettato per essere utilizzato direttamente nei tuoi componenti, al posto del contenuto che sta caricando.

Esaminiamo alcuni motivi per cui abbiamo scelto React Loading Skeleton rispetto ad altri.

Temi

React Loading Skeleton supporta i temi. Pertanto, puoi facilmente cambiare i colori di tutti i componenti dello scheletro usando SkeletonTheme e passare i valori agli props di scena del colore.

Di seguito è riportato un esempio che mostra come funziona:

 import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; <SkeletonTheme color="grey" highlightColor="#444"> <p> <Skeleton height={250} width={300} count={1} /> </p> </SkeletonTheme> <SkeletonTheme color="#990" highlightColor="#550"> <p> <Skeleton height={250} width={300} count={1} /> </p> </SkeletonTheme> 
Effetto tematico in azione
Effetto tema in azione (anteprima grande)

Durata

Oltre height , width e color , possiamo anche specificare una duration .

 <Skeleton duration={2} />

La durata predefinita è 1.2 . Questo determina quanto tempo ci vuole per eseguire un ciclo dell'animazione dello scheletro.

Per saperne di più, consulta la documentazione.

Implementazione dell'interfaccia utente dello schermo scheletro

Ora installeremo react-loading-skeleton . Esegui il seguente comando nel tuo terminale per installare il pacchetto:

 npm install react-loading-skeleton

Componente scheletro

Creiamo un componente scheletro per i nostri dati video. All'interno della nostra cartella components , crea un file SkeletonCard.js e aggiungi il seguente codice:

 import React from "react"; import Skeleton from "react-loading-skeleton"; const SkeletonCard = () => { return ( <section> <h2 className="section-title"> <Skeleton height={30} width={300} /> </h2> <ul className="list"> {Array(9) .fill() .map((item, index) => ( <li className="card" key={index}> <Skeleton height={180} /> <h4 className="card-title"> <Skeleton circle={true} height={50} width={50} />  <Skeleton height={36} width={`80%`} /> </h4> <p className="card-channel"> <Skeleton width={`60%`} /> </p> <div className="card-metrics"> <Skeleton width={`90%`} /> </div> </li> ))} </ul> </section> ); }; export default SkeletonCard;

Abbiamo creato una lista non ordinata. Al suo interno, abbiamo utilizzato il metodo Array.fill() . Poiché abbiamo nove elementi di dati fittizi, abbiamo utilizzato il metodo Array.fill() per scorrere la lunghezza del nostro oggetto items e lo abbiamo riempito senza alcun valore di indice, rendendo quindi il nostro array vuoto . Consulta la documentazione di Array.fill per sapere come funziona.

Successivamente, abbiamo mappato il nostro array vuoto per restituire un elenco contenente le proprietà dello scheletro e abbiamo specificato il valore di ciascuna delle proprietà dello scheletro.

Qui, l' height connota la lunghezza di un rettangolo dello scheletro e la width si riferisce all'ampiezza, mentre il circle crea la parte arrotondata dell'interfaccia utente dello scheletro.

React Loading Skeleton viene fornito con l'animazione Pulse predefinita, il che lo rende a portata di mano. Potresti creare un'animazione Pulse per adattarla al tuo progetto, ma se me lo chiedi, rimarrei con l'impostazione predefinita.

Finalmente è disponibile il codice sorgente completo.

Ora abbiamo un'interfaccia utente dello scheletro completamente funzionale. Il nostro esempio mostra lo scheletro per cinque secondi prima di mostrare il contenuto.

Vediamo il nostro risultato finora:

Interfaccia utente simile a YouTube più interfaccia utente dello schermo scheletro
La nostra interfaccia utente scheletrica simile a YouTube (anteprima grande)

Conclusione

Gli schermi Skeleton migliorano enormemente l'esperienza dell'utente evitando la frustrazione di dover affrontare uno schermo completamente vuoto e dando all'utente un'idea dell'aspetto del contenuto prima del caricamento.

Se non ti senti a tuo agio con nessuno dei pacchetti che abbiamo esaminato, puoi creare la tua interfaccia utente scheletrica creando rettangoli e cerchi che imitano il layout della pagina.

Si prega di condividere il tuo feedback e la tua esperienza nella sezione commenti qui sotto. Mi piacerebbe vedere cosa ti viene in mente!

Il repository di supporto per questo articolo è disponibile su Github.

Riferimenti

  • "Tutto quello che devi sapere sugli schermi Skeleton", Bill Chung, UX Collective
  • "Scheletro che carica pagine con React", Anthony Panagi, Octopus Wealth
  • "Scheletri scheletrici con React and React Native", Chris Dolphin, Alligator.io
  • "Implementazione del caricamento dello scheletro in reazione", Adrian Bece, DEV