Articolo originale: https://www.freecodecamp.org/news/build-portfolio-website-react/

Oggi creerai una delle app più importanti che puoi costruire per te stesso: il tuo portfolio da sviluppatore.

Ogni sviluppatore React o sviluppatore web in generale, deve essere in grado di mostrare ciò che può fare a qualsiasi potenziale cliente o datore di lavoro.

Questo è esattamente ciò che costruiremo in questa guida, con l'aiuto di una serie di strumenti standard del settore, tra cui React, Tailwind CSS e Netlify.

Iniziamo!

Come sarà il Portfolio?

portafoglio-1-min

Questa è la versione finale del portfolio che creerai.

Conterrà informazioni su di te, quali progetti hai realizzato, quali abilità hai utilizzato per realizzare quei progetti e includerà un modulo di contatto per i clienti o i datori di lavoro per contattarti.

Quali strumenti utilizzeremo?

  • Useremo React per creare l'interfaccia utente dell'app. Ci consentirà di comporre ogni parte della nostra landing page attraverso componenti riutilizzabili ed estendere la nostra app se vogliamo aggiungere funzionalità aggiuntive, come un blog.
  • Per definire lo stile della nostra applicazione, utilizzeremo Tailwind CSS. Per dare alla nostra app un aspetto professionale, Tailwind ci consentirà di applicare facilmente più stili combinando i nomi delle classi sui nostri elementi React.
  • Per pubblicare la nostra app sul web, utilizzeremo il servizio gratuito Netlify. Servirà il nostro progetto su un dominio personalizzato per gli utenti molto rapidamente con l'aiuto di una CDN (rete di distribuzione dei contenuti).

Come iniziare

Puoi scaricare i file di partenza per il nostro progetto qui.

Quando prendi il codice, tutto ciò che dovrai fare è trascinare la cartella del progetto (decompresso) nell'editor di codice ed eseguire il comando:

npm install

E sei a posto!

Di quali strumenti ho bisogno per costruire il mio portfolio?

Per eseguire l'intero processo di creazione della nostra app dall'inizio alla distribuzione, dovrai disporre di quanto segue:

  1. Node.js installato sul tuo computer. Puoi scaricarlo su nodejs.org.
  2. Git installato sul tuo computer. Puoi scaricarlo su git-scm.com.
  3. Consiglierei di utilizzare VS Code come editor di codice. Puoi scaricarlo su code.visualstudio.com.
  4. Un account Netlify gratuito su netlify.com.
  5. Un account GitHub gratuito su github.com.

Come costruire la struttura del Portfolio

Il vantaggio dell'utilizzo di React è che potremmo espandere la nostra app a tutte le pagine che vogliamo, molto semplicemente, e aggiungere molti contenuti aggiuntivi.

Tuttavia, poiché stiamo lavorando solo con una pagina, all'interno del nostro componente app possiamo immaginare  molto rapidamente i diversi componenti di cui avremo bisogno. Avremo una barra di navigazione in cima con tutti i collegamenti per passare alle diverse sezioni del nostro portfolio.

Successivamente, includeremo una sezione informazioni, una sezione per i nostri progetti, testimonianze e infine il nostro modulo di contatto.

Questa rapida pianificazione ci consente di capire come devono essere nominati i nostri componenti e in quale ordine. Possiamo andare avanti e aggiungerli tutti al nostro file App.js (in src):

// src/App.js

import React from "react";

export default function App() {
  return (
    <main>
      <Navbar />
      <About />
      <Projects />
      <Skills />
      <Testimonials />
      <Contact />
    </main>
  );
}

Come creare i nostri componenti

Ora che abbiamo elencato tutti questi componenti, dobbiamo andare avanti e crearli.

All'interno della nostra cartella di origine (src), creeremo una cartella chiamata components con tutti i file di cui abbiamo bisogno:

my-portfolio
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
    ├── App.js
    ├── data.js
    ├── index.css
    ├── index.js
    └── components
        ├── About.js
        ├── Contact.js
        ├── Navbar.js
        ├── Projects.js
        ├── Skills.js
        └── Testimonials.js

Quindi creeremo la struttura di base di ogni componente React e la esporteremo da quel file con export default:

// src/components/About.js

export default function About() {}

// ripetere la stessa struttura di base per tutti e 6 i componenti

E infine assicurati di importarlo di nuovo in App.js:

// src/App.js

import React from "react";
import About from "./components/About";
import Contact from "./components/Contact";
import Navbar from "./components/Navbar";
import Projects from "./components/Projects";
import Skills from "./components/Skills";
import Testimonials from "./components/Testimonials";

export default function App() {
  return (
    <main>
      <Navbar />
      <About />
      <Projects />
      <Skills />
      <Testimonials />
      <Contact />
    </main>
  );
}

Nota che ci dovrebbero essere sei componenti in totale.

Introduzione a Tailwind CSS

Una volta fatto, possiamo cominciare a lavorare con Tailwind CSS, in modo da iniziare a dare alla nostra app un aspetto di base.

Il vantaggio dell'utilizzo di Tailwind CSS è che non è necessario scrivere manualmente alcuno stile in un foglio di stile CSS. Tutto quello che dobbiamo fare è combinare più classi per creare l'aspetto che vogliamo.

Ad esempio, per dare al nostro portfolio uno sfondo scuro con testo grigio applicato a tutti i nostri componenti figlio, puoi aggiungere le seguenti classi al nostro elemento main:

// src/App.js

import React from "react";
import About from "./components/About";
import Contact from "./components/Contact";
import Navbar from "./components/Navbar";
import Projects from "./components/Projects";
import Skills from "./components/Skills";
import Testimonials from "./components/Testimonials";

export default function App() {
  return (
    <main className="text-gray-400 bg-gray-900 body-font">
      <Navbar />
      <About />
      <Projects />
      <Skills />
      <Testimonials />
      <Contact />
    </main>
  );
}

Come costruire il componente About

Iniziamo dalla nostra prima sezione, la sezione About. Questo consisterà in un'introduzione di base a noi stessi e alle competenze in cui siamo specializzati.

Includerà anche alcuni collegamenti al modulo di contatto e ai nostri progetti passati. Poiché questi collegamenti saranno in parti diverse della stessa pagina, possiamo utilizzare gli hash: "/#projects" e "/#contact".

Per far funzionare questi collegamenti e per poter saltare a ciascuna sezione, imposteremo l'attributo id della sezione progetti su "projects" e quelli della sezione contatti su "contact".

// src/components/About.js

import React from "react";

export default function About() {
  return (
    <section id="about">
      <div className="container mx-auto flex px-10 py-20 md:flex-row flex-col items-center">
        <div className="lg:flex-grow md:w-1/2 lg:pr-24 md:pr-16 flex flex-col md:items-start md:text-left mb-16 md:mb-0 items-center text-center">
          <h1 className="title-font sm:text-4xl text-3xl mb-4 font-medium text-white">
            Hi, I'm Reed.
            <br className="hidden lg:inline-block" />I love to build amazing
            apps.
          </h1>
          <p className="mb-8 leading-relaxed">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui
            laborum quasi, incidunt dolore iste nostrum cupiditate voluptas?
            Laborum, voluptas natus?
          </p>
          <div className="flex justify-center">
            <a
              href="#contact"
              className="inline-flex text-white bg-green-500 border-0 py-2 px-6 focus:outline-none hover:bg-green-600 rounded text-lg">
              Work With Me
            </a>
            <a
              href="#projects"
              className="ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg">
              See My Past Work
            </a>
          </div>
        </div>
        <div className="lg:max-w-lg lg:w-full md:w-1/2 w-5/6">
          <img
            className="object-cover object-center rounded"
            alt="hero"
            src="./coding.svg"
          />
        </div>
      </div>
    </section>
  );
}

Per l'immagine sul lato destro della sezione, sto usando un file svg dalla cartella public, coding.svg.

Questa immagine funge semplicemente da segnaposto temporaneo. Consiglio vivamente di utilizzare un'immagine reale di te stesso.

Come costruire il componente Projects

La nostra sezione progetti sarà composta da un elemento section con una id di "projects". Questo conterrà una galleria di tutti i progetti che abbiamo creato, che includerà immagini.

Avrà il titolo del progetto, insieme alle tecnologie che abbiamo utilizzato per realizzarlo, e un collegamento ad esso (se è distribuito).

// src/components/Projects.js

import { CodeIcon } from "@heroicons/react/solid";
import React from "react";
import { projects } from "../data";

export default function Projects() {
  return (
    <section id="projects" className="text-gray-400 bg-gray-900 body-font">
      <div className="container px-5 py-10 mx-auto text-center lg:px-40">
        <div className="flex flex-col w-full mb-20">
          <CodeIcon className="mx-auto inline-block w-10 mb-4" />
          <h1 className="sm:text-4xl text-3xl font-medium title-font mb-4 text-white">
            Apps I've Built
          </h1>
          <p className="lg:w-2/3 mx-auto leading-relaxed text-base">
            Lorem ipsum, dolor sit amet consectetur adipisicing elit. Explicabo
            facilis repellat ab cupiditate alias vero aliquid obcaecati quisquam
            fuga dolore.
          </p>
        </div>
        <div className="flex flex-wrap -m-4">
          {projects.map((project) => (
            <a
              href={project.link}
              key={project.image}
              className="sm:w-1/2 w-100 p-4">
              <div className="flex relative">
                <img
                  alt="gallery"
                  className="absolute inset-0 w-full h-full object-cover object-center"
                  src={project.image}
                />
                <div className="px-8 py-10 relative z-10 w-full border-4 border-gray-800 bg-gray-900 opacity-0 hover:opacity-100">
                  <h2 className="tracking-widest text-sm title-font font-medium text-green-400 mb-1">
                    {project.subtitle}
                  </h2>
                  <h1 className="title-font text-lg font-medium text-white mb-3">
                    {project.title}
                  </h1>
                  <p className="leading-relaxed">{project.description}</p>
                </div>
              </div>
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}

Nota che useremo anche la libreria @heroicons/react per poter scrivere alcune icone SVG come componenti di React.

Stiamo importando una serie di progetti da un file data.js nella stessa cartella. Lì stiamo esportando una serie di oggetti che includono ciascuno i dati di un singolo progetto:

// src/data.js

export const projects = [
  {
    title: "React Reserve",
    subtitle: "MERN Stack",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-1.gif",
    link: "https://reactbootcamp.com",
  },
  {
    title: "React Tracks",
    subtitle: "React and Python",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-2.gif",
    link: "https://reedbarger.com",
  },
  {
    title: "DevChat",
    subtitle: "React and Firebase",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-3.gif",
    link: "https://jsbootcamp.com",
  },
  {
    title: "Epic Todo App",
    subtitle: "React Hooks",
    description:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium dolore rerum laborum iure enim sint nemo omnis voluptate exercitationem eius?",
    image: "./project-4.gif",
    link: "https://pythonbootcamp.com",
  },
];

Come costruire il componente delle Skills

Compiliamo la sezione per tutte le competenze e le tecnologie che conosciamo.

Questo consisterà in un semplice elenco di tutti i principali strumenti con cui abbiamo familiarità e che possiamo utilizzare nei progetti dei nostri datori di lavoro o clienti.

Ancora una volta, importeremo un array dalla nostra cartella dati. Ma questo array è costituito da un numero di stringhe che rappresentano ciascuna delle abilità che conosciamo come JavaScript, React e Node:

// src/components/Skills.js

import { BadgeCheckIcon, ChipIcon } from "@heroicons/react/solid";
import React from "react";
import { skills } from "../data";

export default function Skills() {
  return (
    <section id="skills">
      <div className="container px-5 py-10 mx-auto">
        <div className="text-center mb-20">
          <ChipIcon className="w-10 inline-block mb-4" />
          <h1 className="sm:text-4xl text-3xl font-medium title-font text-white mb-4">
            Skills &amp; Technologies
          </h1>
          <p className="text-base leading-relaxed xl:w-2/4 lg:w-3/4 mx-auto">
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nisi sit
            ipsa delectus eum quo voluptas aspernatur accusantium distinctio
            possimus est.
          </p>
        </div>
        <div className="flex flex-wrap lg:w-4/5 sm:mx-auto sm:mb-2 -mx-2">
          {skills.map((skill) => (
            <div key={skill} className="p-2 sm:w-1/2 w-full">
              <div className="bg-gray-800 rounded flex p-4 h-full items-center">
                <BadgeCheckIcon className="text-green-400 w-6 h-6 flex-shrink-0 mr-4" />
                <span className="title-font font-medium text-white">
                  {skill}
                </span>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

Come costruire il componente Testimonials

Nella componente Testimonials, elencheremo un paio di testimonianze, magari di clienti passati o di persone che hanno familiarità con il nostro lavoro.

Questi consisteranno in un paio di cards che mostreranno la testimonianza stessa, come anche da chi proviene e l'azienda da cui proviene questa persona.

Stiamo anche importando una array di testimonianze con una serie di oggetti che presentano la citazione, l'immagine, il nome e l'azienda.

// src/components/Testimonials

import React from "react";
import { TerminalIcon, UsersIcon } from "@heroicons/react/solid";
import { testimonials } from "../data";

export default function Testimonials() {
  return (
    <section id="testimonials">
      <div className="container px-5 py-10 mx-auto text-center">
        <UsersIcon className="w-10 inline-block mb-4" />
        <h1 className="sm:text-4xl text-3xl font-medium title-font text-white mb-12">
          Client Testimonials
        </h1>
        <div className="flex flex-wrap m-4">
          {testimonials.map((testimonial) => (
            <div className="p-4 md:w-1/2 w-full">
              <div className="h-full bg-gray-800 bg-opacity-40 p-8 rounded">
                <TerminalIcon className="block w-8 text-gray-500 mb-4" />
                <p className="leading-relaxed mb-6">{testimonial.quote}</p>
                <div className="inline-flex items-center">
                  <img
                    alt="testimonial"
                    src={testimonial.image}
                    className="w-12 rounded-full flex-shrink-0 object-cover object-center"
                  />
                  <span className="flex-grow flex flex-col pl-4">
                    <span className="title-font font-medium text-white">
                      {testimonial.name}
                    </span>
                    <span className="text-gray-500 text-sm uppercase">
                      {testimonial.company}
                    </span>
                  </span>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

Come costruire il componente Contact

Alla fine della nostra landing page, includeremo il nostro modulo di contatto per consentire ai potenziali datori di lavoro di contattarci.

Questo modulo avrà 3 campi di inserimento: un nome, un'e-mail e un campo per scrivere il messaggio.

Per gestire questi invii di moduli, utilizzeremo lo strumento Netlify Forms per occuparci molto facilmente del salvataggio di quei messaggi.

// src/components/Contact.js

import React from "react";

export default function Contact() {
  return (
    <section id="contact" className="relative">
      <div className="container px-5 py-10 mx-auto flex sm:flex-nowrap flex-wrap">
        <div className="lg:w-2/3 md:w-1/2 bg-gray-900 rounded-lg overflow-hidden sm:mr-10 p-10 flex items-end justify-start relative">
          <iframe
            width="100%"
            height="100%"
            title="map"
            className="absolute inset-0"
            frameBorder={0}
            marginHeight={0}
            marginWidth={0}
            style={{ filter: "opacity(0.7)" }}
            src="https://www.google.com/maps/embed/v1/place?q=97+warren+st+new+york+city&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8"
          />
          <div className="bg-gray-900 relative flex flex-wrap py-6 rounded shadow-md">
            <div className="lg:w-1/2 px-6">
              <h2 className="title-font font-semibold text-white tracking-widest text-xs">
                ADDRESS
              </h2>
              <p className="mt-1">
                97 Warren St. <br />
                New York, NY 10007
              </p>
            </div>
            <div className="lg:w-1/2 px-6 mt-4 lg:mt-0">
              <h2 className="title-font font-semibold text-white tracking-widest text-xs">
                EMAIL
              </h2>
              <a className="text-indigo-400 leading-relaxed">
                reedbarger@email.com
              </a>
              <h2 className="title-font font-semibold text-white tracking-widest text-xs mt-4">
                PHONE
              </h2>
              <p className="leading-relaxed">123-456-7890</p>
            </div>
          </div>
        </div>
        <form
          netlify
          name="contact"
          className="lg:w-1/3 md:w-1/2 flex flex-col md:ml-auto w-full md:py-8 mt-8 md:mt-0">
          <h2 className="text-white sm:text-4xl text-3xl mb-1 font-medium title-font">
            Hire Me
          </h2>
          <p className="leading-relaxed mb-5">
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Illum
            suscipit officia aspernatur veritatis. Asperiores, aliquid?
          </p>
          <div className="relative mb-4">
            <label htmlFor="name" className="leading-7 text-sm text-gray-400">
              Name
            </label>
            <input
              type="text"
              id="name"
              name="name"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
            />
          </div>
          <div className="relative mb-4">
            <label htmlFor="email" className="leading-7 text-sm text-gray-400">
              Email
            </label>
            <input
              type="email"
              id="email"
              name="email"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
            />
          </div>
          <div className="relative mb-4">
            <label
              htmlFor="message"
              className="leading-7 text-sm text-gray-400">
              Message
            </label>
            <textarea
              id="message"
              name="message"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 h-32 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out"
            />
          </div>
          <button
            type="submit"
            className="text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg">
            Submit
          </button>
        </form>
      </div>
    </section>
  );
}

Come incorporare una posizione di Google Maps

A sinistra del modulo includeremo una mappa di Google incorporata in Google Maps di dove ci troviamo.

Possiamo farlo con l'aiuto di uno strumento online: embed-map.com. Tutto quello che devi fare è inserire la tua posizione e premere "Generate HTML code".

Nel riga che ci viene fornita, non copiare tutto il codice, solo l'attributo src dell'elemento iframe. Sostituiremo quel valore con il valore src predefinito che abbiamo nel nostro iframe.

portafoglio-2

Per inviare i dati dei moduli a Netlify, Netlify Forms deve riconoscere un modulo come HTML statico. Poiché la nostra app React è controllata da JavaScript e non è costituita da comune HTML, è necessario aggiungere un modulo nascosto al nostro file index.html nella cartella pubblica.

<!-- public/index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- contenuto di head saltato -->
  </head>
  <body>

  <form name="contact" netlify netlify-honeypot="bot-field" hidden>
    <input type="text" name="name" />
    <input type="email" name="email" />
    <textarea name="message"></textarea>
  </form>
  
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

Abbiamo bisogno di nascondere questo modulo, perché non è necessario che venga visualizzato dall'utente ma solo da Netlify.

Gli daremo l'attributo hidden e  l'attributo name che corrisponde al modulo JSX in Contact.js. Dobbiamo anche assegnargli l'attributo netlify in modo che Netlify Forms lo riconosca. Infine, dobbiamo includere tutti gli stessi campi di input del nostro modulo JSX:  name, email, message.

Come inviare il modulo di contatto

Una volta fatto, torneremo a Contact.js. Useremo JavaScript per inviare questo modulo.

Prima di tutto, creeremo uno stato dedicato per ciascuno dei valori digitati nel modulo per name, email, message:

const [name, setName] = React.useState("");
const [email, setEmail] = React.useState("");
const [message, setMessage] = React.useState("");

Memorizziamo ciò che l'utente digita in ciascuno degli input nello stato con l'aiuto dell'handler  onChange.

Per gestire l'invio del modulo, aggiungeremo il prop onSubmit ad esso. La funzione che verrà chiamata, handleSubmit, effettuerà una richiesta di post all'endpoint "/" con tutti i nostri dati del modulo.

Imposteremo le intestazioni della richiesta per indicare che stiamo inviando i dati del modulo. Per il corpo della richiesta, includeremo il nome del modulo e tutti i dati del modulo tramite le variabili di stato  name, email e message.

// src/components/Contact.js

import React from "react";

export default function Contact() {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [message, setMessage] = React.useState("");

  function encode(data) {
    return Object.keys(data)
      .map(
        (key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key])
      )
      .join("&");
  }

  function handleSubmit(e) {
    e.preventDefault();
    fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": "contact", name, email, message }),
    })
      .then(() => alert("Message sent!"))
      .catch((error) => alert(error));
  }

  return (
    <section id="contact" className="relative">
      <div className="container px-5 py-10 mx-auto flex sm:flex-nowrap flex-wrap">
        <div className="lg:w-2/3 md:w-1/2 bg-gray-900 rounded-lg overflow-hidden sm:mr-10 p-10 flex items-end justify-start relative">
          <iframe
            width="100%"
            height="100%"
            title="map"
            className="absolute inset-0"
            frameBorder={0}
            marginHeight={0}
            marginWidth={0}
            style={{ filter: "opacity(0.7)" }}
            src="https://www.google.com/maps/embed/v1/place?q=97+warren+st+new+york+city&key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8"
          />
          <div className="bg-gray-900 relative flex flex-wrap py-6 rounded shadow-md">
            <div className="lg:w-1/2 px-6">
              <h2 className="title-font font-semibold text-white tracking-widest text-xs">
                ADDRESS
              </h2>
              <p className="mt-1">
                97 Warren St. <br />
                New York, NY 10007
              </p>
            </div>
            <div className="lg:w-1/2 px-6 mt-4 lg:mt-0">
              <h2 className="title-font font-semibold text-white tracking-widest text-xs">
                EMAIL
              </h2>
              <a className="text-indigo-400 leading-relaxed">
                reedbarger@email.com
              </a>
              <h2 className="title-font font-semibold text-white tracking-widest text-xs mt-4">
                PHONE
              </h2>
              <p className="leading-relaxed">123-456-7890</p>
            </div>
          </div>
        </div>
        <form
          netlify
          name="contact"
          onSubmit={handleSubmit}
          className="lg:w-1/3 md:w-1/2 flex flex-col md:ml-auto w-full md:py-8 mt-8 md:mt-0">
          <h2 className="text-white sm:text-4xl text-3xl mb-1 font-medium title-font">
            Hire Me
          </h2>
          <p className="leading-relaxed mb-5">
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Illum
            suscipit officia aspernatur veritatis. Asperiores, aliquid?
          </p>
          <div className="relative mb-4">
            <label htmlFor="name" className="leading-7 text-sm text-gray-400">
              Name
            </label>
            <input
              type="text"
              id="name"
              name="name"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
              onChange={(e) => setName(e.target.value)}
            />
          </div>
          <div className="relative mb-4">
            <label htmlFor="email" className="leading-7 text-sm text-gray-400">
              Email
            </label>
            <input
              type="email"
              id="email"
              name="email"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 text-base outline-none text-gray-100 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>
          <div className="relative mb-4">
            <label
              htmlFor="message"
              className="leading-7 text-sm text-gray-400">
              Message
            </label>
            <textarea
              id="message"
              name="message"
              className="w-full bg-gray-800 rounded border border-gray-700 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-900 h-32 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out"
              onChange={(e) => setMessage(e.target.value)}
            />
          </div>
          <button
            type="submit"
            className="text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg">
            Submit
          </button>
        </form>
      </div>
    </section>
  );
}

Come puoi vedere sopra, stiamo codificando i dati del modulo con una funzione speciale encode che vedi qui.

Se il messaggio viene inviato correttamente, visualizzeremo un avviso che dice "Message sent". Altrimenti, se si verifica un errore, avviseremo l'utente di tale situazione.

Come costruire il componente Navbar

L'ultimo passaggio è creare il nostro componente Navbar.

Vogliamo che questa barra di navigazione rimanga in cima alla nostra app su dispositivi di grandi dimensioni e non sia ferma sullo schermo su dispositivi mobili.

Inoltre, vogliamo includere collegamenti a ciascuna delle nostre sezioni importanti per il nostro progetto come capacità, testimonianze e il nostro modulo di contatto:

// src/components/Navbar.js

import { ArrowRightIcon } from "@heroicons/react/solid";
import React from "react";

export default function Navbar() {
  return (
    <header className="bg-gray-800 md:sticky top-0 z-10">
      <div className="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center">
        <a className="title-font font-medium text-white mb-4 md:mb-0">
          <a href="#about" className="ml-3 text-xl">
            Reed Barger
          </a>
        </a>
        <nav className="md:mr-auto md:ml-4 md:py-1 md:pl-4 md:border-l md:border-gray-700	flex flex-wrap items-center text-base justify-center">
          <a href="#projects" className="mr-5 hover:text-white">
            Past Work
          </a>
          <a href="#skills" className="mr-5 hover:text-white">
            Skills
          </a>
          <a href="#testimonials" className="mr-5 hover:text-white">
            Testimonials
          </a>
        </nav>
        <a
          href="#contact"
          className="inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0">
          Hire Me
          <ArrowRightIcon className="w-4 h-4 ml-1" />
        </a>
      </div>
    </header>
  );
}

In che modo questo componente rimane in cima alla pagina su un dispositivo più grande? Con l'aiuto della classe md:sticky sul nostro elemento header.

Questa classe significa che avrà la regola di stile position: sticky; applicata a partire da un punto di interruzione di medie dimensioni (768px).

Come distribuire il tuo Portfolio

Ora per rendere attivo il nostro portfolio, dobbiamo trasferire la nostra applicazione su GitHub.

Se non hai familiarità con Git e GitHub, sarebbe necessario un po' di tempo solo per imparare a come inviare il tuo codice al tuo account GitHub per la prima volta. È un'abilità essenziale che qualsiasi sviluppatore deve conoscere.

Dopo aver acquisito familiarità con questo processo, possiamo prima creare un nuovo repository Github. Successivamente, eseguiremo git add ., git commit -m "Deploy", creando il nostro git remoto e quindi git push -u origin master.

Una volta che il nostro progetto è su GitHub, possiamo andare su Netlify e selezionare l'opzione "Choose Site from Git". Quindi sceglieremo GitHub per la nostra distribuzione continua e selezioneremo il repository GitHub in cui abbiamo appena inviato il nostro codice.

portafoglio-3-min

Dopodiché, il nostro progetto verrà pubblicato automaticamente sul web!

Cosa viene dopo

Congratulazioni! Ora hai un'app  portfolio live sul Web che mostra tutti i tuoi progetti e le tue abilità ai potenziali datori di lavoro.

Il prossimo passo da fare sarebbe impostare un dominio personalizzato, preferibilmente con il tuo nome (es. reedbarger.com ). Poiché Netlify include un DNS, puoi facilmente configurare un dominio personalizzato con loro.

Cerca di aggiungere un blog alla tua app React per mostrare ancora di più la tua conoscenza da sviluppatore ai potenziali datori di lavoro.

Rendi il tuo portfolio personale un'espressione di te stesso e di ciò che ti appassiona come sviluppatore e avrai successo!

Vuoi il modo n. 1 per imparare React?

Il Bootcamp React prende tutto ciò che dovresti sapere sull'apprendimento di React e lo raggruppa in un unico pacchetto completo, inclusi video, cheatsheet e bonus speciali.

Ottieni le informazioni privilegiate che centinaia di sviluppatori hanno già utilizzato per padroneggiare React, per trovare il lavoro dei loro sogni e assumere il controllo del loro futuro:

Il Bootcamp di reazione


Clicca qui per essere avvisato quando apre.