Bygg responsive komponenter i Gatsby med artsy/fresnel

Skrevet av Yomi Eluwande ✏️

En av funksjonene til moderne nettutvikling er å kunne vise bestemte sider eller deler av en side basert på skjermstørrelsen til brukerens enhet. Dette er ellers kjent som responsiv webdesign.

Responsivt webdesign lar oss sikre at brukeren får den beste versjonen av nettsiden uavhengig av enhet, plattform, skjermstørrelse og skjermorientering.

I denne artikkelen lærer vi hvordan du bygger responsive komponenter i React ved å bruke @artsy/fresnel-pakken.

Hva er artsy/fresnel-pakken?

@artsy/fresnel er en SSR-tilnærming til responsive komponenter i React.

Ved å bruke <Media /> komponent, kan du spesifisere hva komponenten viser ved et bestemt bruddpunkt, mellom en rekke bruddpunkter. <Media /> komponent aksepterer rekvisitter som hjelper deg med å bestemme responsen til appene dine. Noen av dem er:

kl

Denne egenskapen viser komponenter bare hvis gjeldende visningsport samsvarer med det spesifikke brytepunktsettet.

<Media at="sm" />

mindre enn

Denne egenskapen viser komponenter bare når gjeldende visningsport er mindre enn det angitte spesifikke bruddpunktet.

<Media lessThan="md" />

større enn

Denne egenskapen viser komponenter bare når gjeldende visningsport er større enn det spesifikke bruddpunktet.

<Media greaterThan="lg" />

greaterThanOrEqual

Denne egenskapen viser komponenter bare når gjeldende visningsport er større enn eller lik det spesifikke brytepunktsettet.

<Media greaterThanOrEqual="md" />

mellom

Denne egenskapen viser komponenter når gjeldende visningsport samsvarer med intervallet med bruddpunkter som er spesifisert.

<Media between={['md', 'lg']} />

For å se hvordan artsy/fresnel-pakken fungerer, legger vi den til en Gatsby-side og bruker den til å bygge responsive komponenter. Gatsby-nettstedet vil være et magasin som viser en liste over artikler.

Opprette et Gatsby-nettsted

For å opprette et Gatsby-nettsted, må du installere Gatsby CLI. Gatsby CLI-verktøyet lar deg raskt lage nye Gatsby-drevne nettsteder og kjøre kommandoer for å utvikle Gatsby-nettsteder. Den kan installeres globalt ved å kjøre kommandoen nedenfor:

yarn global add gatsby-cli

Når det er gjort, vil neste trinn være å lage et Gatsby-nettsted. Som nevnt ovenfor vil vi bruke Gatsby CLI-verktøyet til å lage din første Gatsby-side, og vi tar et av startprosjektene til å begynne med – Gatsby-standardstarteren:

gatsby new artsy-fresnel-example

Når kommandoen ovenfor er utført, bør du ha en ny katalog kalt artsy-fresnel-example med alle filene som trengs slik:



Før vi går videre til innholdet i denne artikkelen, la oss flytte rundt på ting og omorganisere komponentene i artsy-fresnel-example katalog.

Vi kommer til å bruke metoden for gruppering etter funksjoner eller ruter, som i hovedsak er å sette CSS, JS og tester sammen i mapper gruppert etter funksjon eller komponenter.

Dette betyr at for hver komponent i src/components , har vi en tilsvarende mappe for det, f.eks. header.js filen vil nå være i en mappe kalt Header og omdøpt til index.js . Gjør det samme for resten av komponentene. Katalogen din skal være lik den nedenfor:

Sørg for å oppdatere banene til de ulike filimportene etter behov.

Så for å gi en oversikt over hva vi prøver å bygge her, skal vi bygge en magasinside som viser nøyaktig fire artikler. Den første artikkelen vil være en fremhevet artikkel, og de resterende tre vil være under den i en rad på tre. Det er skrivebordsvisningen.

For mobilvisningen vil alle artiklene være oppført i én kolonne, ingen fremhevet artikkel. For å hjelpe deg med å visualisere det som er beskrevet ovenfor, ta en titt på bildet nedenfor.

La oss lage en ny katalog kalt Articles i src/components katalog, etter det, lag to filer i den nye katalogen – index.js og styles.js .

Vi lager en styles.js fil fordi vi skal bruke styled-components for å style komponentene våre, så fortsett og installer pakken med kommandoen nedenfor:

yarn add styled-components

Deretter åpner du src/components/Articles/index.js fil og legg til denne koden i filen:

// src/components/Articles/index.js
import React from "react"

const articles = []

const Articles = () => {
  return <p>Articles</p>
}

export default Articles

index.js fil er komponenten som er ansvarlig for å vise artiklene, og derfor trenger vi en datakilde for artiklene. Du kan hente innholdet i kodebiten nedenfor og bruke den til å erstatte const articles = [] kodelinje:

const articles = [
  {
    id: "1",
    date: "01-01-2020",
    headline: "Lorem ipsum dolor sit amet apem edit",
    category: "Lifestyle",
    snippet:
      "Cras a erat a quam efficitur vestibulum. Nulla in nisl semper, condimentum ex quis, semper elit.",
    image:
      "https://images.unsplash.com/photo-1579541707963-368970b955b7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80",
  },
  {
    id: "2",
    date: "02-01-2020",
    headline: "Lorem ipsum dolor sit amet apem edit",
    category: "Lifestyle",
    snippet:
      "Cras a erat a quam efficitur vestibulum. Nulla in nisl semper, condimentum ex quis, semper elit.",
    image:
      "https://images.unsplash.com/photo-1579571076332-acc4483d3eb8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1023&q=80",
  },
  {
    id: "3",
    date: "03-01-2020",
    headline: "Lorem ipsum dolor sit amet apem edit",
    category: "Lifestyle",
    snippet:
      "Cras a erat a quam efficitur vestibulum. Nulla in nisl semper, condimentum ex quis, semper elit.",
    image:
      "https://images.unsplash.com/photo-1579617881900-fe2590bc8384?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80",
  },
  {
    id: "4",
    date: "04-01-2020",
    headline: "Lorem ipsum dolor sit amet apem edit",
    category: "Lifestyle",
    snippet:
      "Cras a erat a quam efficitur vestibulum. Nulla in nisl semper, condimentum ex quis, semper elit.",
    image:
      "https://images.unsplash.com/photo-1579626349272-8ecb1eba0421?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80",
  },
]

Deretter åpner du styles.js fil og legg til koden nedenfor:

// src/components/Articles/styles.js

import styled from "styled-components"

export const Articles = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(235px, 1fr));
  gap: 1rem;
  margin-top: 2rem;
  @media (min-width: 720px) {
    grid-template-columns: repeat(3, minmax(235px, 1fr));
  }
`
export const Card = styled.div`
  padding-right: 0;
  border-right: none;
  img {
    margin-bottom: 0;
  }
  &:last-child {
    border-right: none;
  }
  @media (min-width: 720px) {
    border-right: 1px solid rgb(226, 226, 226);
    padding-right: 1rem;
  }
`
export const Headline = styled.p`
  font-weight: 600;
  color: #121212;
  font-size: 0.95rem;
`
export const FooterText = styled.p`
  color: #999999;
  font-size: 0.8rem;
`

Koden ovenfor hjelper til med å bygge raden med artikler som skal vises på artikkelsiden. Alt vi trenger å gjøre er å bruke dem i index.js fil:

// src/components/Articles/index.js

import React from "react"

import * as Styles from "./styles"

const articles = [...] // articles from https://gist.github.com/yomete/53be226f779d4d1ebd3ed85b8fa5672a

const Articles = () => {

  const featuredArticle = articles.slice(0, 1)
  const desktopArticleGrids = articles.slice(1, 4)
  const mobileArticleGrids = articles.slice(0, 4)

  return (
    <Styles.Articles>
      {desktopArticleGrids.map(article => (
        <Styles.Card>
          <img src={article.image}></img>
          <Styles.Headline>{article.headline}</Styles.Headline>
          <Styles.FooterText>
            {article.category} {article.date}
          </Styles.FooterText>
        </Styles.Card>
      ))}
    </Styles.Articles>
  )
}
export default Articles

I kodeblokken ovenfor tildeler vi kilden til artiklene til en const variabel kalt articles . Vi bruker da innholdet i articles for å lage dataene vi trenger for:

  1. Artikkelen som skal brukes for den fremhevede artikkelen, featuredArticle . I dette tilfellet er det den første artikkelen i matrisen
  2. Listen over artikler som skal brukes for artikkelraden på skrivebordet, desktopArticleGrids . Det er de tre siste artiklene i en rekke med fire artikler
  3. Listen over artikler som skal brukes på mobil, mobileArticleGrids

La oss deretter bruke Articles komponent på hjemmesiden til Gatsby-nettstedet. Naviger til src/pages/index.js fil og rediger den med kodeblokken nedenfor:

import React from "react"

import Articles from "../components/Articles/index"
import Layout from "../components/Layout/index"
import SEO from "../components/SEO/index"

const IndexPage = () => (
  <Layout>
    <Articles />
    <SEO title="Home" />
  </Layout>
)

export default IndexPage

Vi kan sjekke Gatsby-siden nå for å se om listen over artikler dukker opp. Du kan gjøre det ved å kjøre denne kommandoen:

yarn start

På dette tidspunktet har vi ordnet artikkelraden, la oss bygge komponenten for de fremhevede artiklene neste gang.

Opprett en ny katalog kalt FeaturedArticle i src/components katalog, etter det, lag to filer i den nye katalogen – index.js og styles.js :

// src/components/FeaturedArticle/index.js

import React from "react"
import * as Styles from "./styles"

const FeaturedArticle = ({ article }) => {
  return (
    <Styles.FeaturedArticleWrapper>
      <Styles.ArticleDetails>
        <Styles.Headline>{article.headline}</Styles.Headline>
        <Styles.Snippet>{article.snippet}</Styles.Snippet>
        <Styles.Date>{article.date}</Styles.Date>
      </Styles.ArticleDetails>
      <Styles.ImageWrapper>
        <img src={article.image}></img>
      </Styles.ImageWrapper>
    </Styles.FeaturedArticleWrapper>
  )
}
export default FeaturedArticle

FeaturedArticle er en funksjonell komponent som godtar article som en egenskap og article objektet brukes deretter til å gi informasjonen som trengs for å bygge komponenten.

Deretter åpner du styles.js fil og rediger med kodeblokken nedenfor:

// src/components/FeaturedArticle/styles.js
import styled from "styled-components"

export const FeaturedArticleWrapper = styled.div`
  display: flex;
  border-top: 1px solid #121212;
  border-bottom: 1px solid #121212;
  padding: 18px 0;
`
export const ImageWrapper = styled.div`
  img {
    margin-bottom: 0;
  }
`
export const Headline = styled.p`
  font-weight: 600;
`
export const Snippet = styled.p`
  color: #555555;
`
export const Date = styled.p`
  color: #999999;
`
export const ArticleDetails = styled.div`
  display: flex;
  flex-direction: column;
`

I koden ovenfor legger vi til stilene som trengs for å bygge den fremhevede artikkelkomponenten.

Deretter bruker vi <FeaturedArticle /> komponent i Article komponent. Åpne src/components/Articles/index.js fil og rediger med kodeblokken nedenfor:

// src/components/Articles/index.js
import React from "react"

import FeaturedArticle from "../FeaturedArticle/index"
import * as Styles from "./styles"

const articles = [...] // articles from https://gist.github.com/yomete/53be226f779d4d1ebd3ed85b8fa5672a

const Articles = () => {

  const featuredArticle = articles.slice(0, 1)
  const desktopArticleGrids = articles.slice(1, 4)
  const mobileArticleGrids = articles.slice(0, 4)

  return (
    <>
      <FeaturedArticle article={featuredArticle[0]} />

      <Styles.Articles>
        {desktopArticleGrids.map(article => (
          <Styles.Card>
            <img src={article.image}></img>
            <Styles.Headline>{article.headline}</Styles.Headline>
            <Styles.FooterText>
              {article.category} {article.date}
            </Styles.FooterText>
          </Styles.Card>
        ))}
      </Styles.Articles>
    </>
  )
}

export default Articles

I kodeblokken ovenfor, FeaturedArticle komponenten importeres og brukes deretter i Articles komponent. Vi gir det også det første elementet i arrayen av artikler, dette vil deretter bli brukt til å fylle ut den fremhevede artikkelkomponenten.

Du kan nå sjekke Gatsby-nettstedet, og det skal se ut som bildet nedenfor:

Legg til artsy/fresnel-pakken

For å installere artsy/fresnel pakken, kjør kommandoen nedenfor i terminalen:

yarn add @artsy/fresnel

For å begynne å bruke artsy-fresnel pakke, må vi gjøre noe oppsett.

Først må vi injisere @artsy/fresnel-stiler inn i hodet på nettstedets index.html. Dette er ikke en fil som er lett tilgjengelig i et Gatsby-oppsett. Du må opprette en html.js fil i src mappe og Gatsby vet å bruke den som en tilpasset index.html fil. Opprett html.js fil og rediger med kodeblokken nedenfor:

import React from "react"
import PropTypes from "prop-types"
import { mediaStyles } from "./Media"
export default function HTML(props) {
  return (
    <html {...props.htmlAttributes}>
      <head>
        <title>Old Times York</title>
        <meta charSet="utf-8" />
        <meta httpEquiv="x-ua-compatible" content="ie=edge" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        {/* Inject @artsy/fresnel styles in to the head */}
        <style>{mediaStyles}</style>
        {props.headComponents}
      </head>
      <body {...props.bodyAttributes}>
        {props.preBodyComponents}
        <noscript key="noscript" id="gatsby-noscript">
          This app works best with JavaScript enabled.
        </noscript>
        <div
          key={`body`}
          id="___gatsby"
          dangerouslySetInnerHTML={{ __html: props.body }}
        />
        {props.postBodyComponents}
      </body>
    </html>
  )
}
HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

Kodeblokken ovenfor er den tilpassede html.js som Gatsby anbefaler med noen få tillegg. mediaStyles er importert fra en Media.js filen som vi skal lage neste gang, og innholdet blir injisert i head av html.js fil.

Den neste tingen å gjøre er å konfigurere @artsy/fresnel i en fil som kan brukes i hele appen. Opprett en src/Media.js fil og rediger med koden nedenfor:

// src/Media.js
import { createMedia } from "@artsy/fresnel"
const QueryBreakpoints = createMedia({
  breakpoints: {
    sm: 0,
    md: 768,
    lg: 1024,
    xl: 1192,
  },
})
// Generate CSS to be injected into the head
export const mediaStyles = QueryBreakpoints.createMediaStyle()
export const { Media, MediaContextProvider } = QueryBreakpoints

I filen ovenfor definerer vi bruddpunktene som trengs for designen din for å produsere settet med mediekomponenter du kan bruke gjennom hele applikasjonen.

Måten @artsy/fresnel pakken fungerer er at alle bruddpunkter gjengis av serveren og hver Media komponenten er pakket inn av vanlig CSS som bare viser det bruddpunktet hvis det samsvarer med brukerens gjeldende nettleserstørrelse. Det er derfor vi trengte å definere bruddpunktene ovenfor.

Den neste tingen å gjøre er å vikle Gatsby-appen rundt MediaContextProvider . MediaContextProvider komponent påvirker hvordan Media komponenter vil bli gjengitt.

I en Gatsby-app kan dette gjøres ved å bruke wrapRootElement API. WrapRootElement lar en plugin pakke inn rotelementet. Dette er nyttig for å sette opp eventuelle leverandørkomponenter som skal omslutte applikasjonen din, i dette tilfellet MediaContextProvider .

Stedet å gjøre det ville være innenfor gatsby-browser.js og gatsby-ssr.js filer. Åpne hver fil og legg til den respektive koden nedenfor:

// gatsby-browser.js
import * as React from "react"
import { MediaContextProvider } from "./src/Media"

export const wrapRootElement = ({ element }) => (
  {element}
)
// gatsby-ssr.js
import * as React from "react"
import { MediaContextProvider } from "./src/Media"

export const wrapRootElement = ({ element }) => (
  {element}
)

Vi gjentar koden ovenfor i to filer fordi hvis du bruker en av wrapRootElement eller wrapPageElement APIer, du må legge det til i begge gatsby-ssr.js og gatsby-browser.js filer slik at sider generert gjennom SSR med Node.js er de samme etter å ha blitt hydrert med JavaScript i nettleseren.

Det er alt oppsettet vi trenger, vi kan nå begynne å bruke <Media /> komponenter i appen vår. Naviger til src/components/Articles/index.js fil og rediger med koden nedenfor:

import React from "react"

import { Media } from "../../Media"
import FeaturedArticle from "../FeaturedArticle/index"
import * as Styles from "./styles"

const articles = [...] // articles from https://gist.github.com/yomete/53be226f779d4d1ebd3ed85b8fa5672a

const Articles = () => {
  const featuredArticle = articles.slice(0, 1)
  const desktopArticleGrids = articles.slice(1, 4)
  const mobileArticleGrids = articles.slice(0, 4)
  return (
    <>
      <Media lessThan="md">
        <Styles.Articles>
          {mobileArticleGrids.map(article => (
            <Styles.Card>
              <img src={article.image}></img>
              <Styles.Headline>{article.headline}</Styles.Headline>
              <Styles.FooterText>
                {article.category} {article.date}
              </Styles.FooterText>
            </Styles.Card>
          ))}
        </Styles.Articles>
      </Media>
      <Media greaterThanOrEqual="md">
        <FeaturedArticle article={featuredArticle[0]} />
        <Styles.Articles>
          {desktopArticleGrids.map(article => (
            <Styles.Card>
              <img src={article.image}></img>
              <Styles.Headline>{article.headline}</Styles.Headline>
              <Styles.FooterText>
                {article.category} {article.date}
              </Styles.FooterText>
            </Styles.Card>
          ))}
        </Styles.Articles>
      </Media>
    </>
  )
}
export default Articles

I kodeblokken ovenfor bruker vi lessThan egenskap for å vise alle artikler samtidig i en liste uten noen fremhevet artikkel, så lenge gjeldende skjermstørrelse er mindre enn bruddpunktet satt til md .

greaterThanOrEqual prop brukes til å vise den fremhevede artikkelen først, og deretter en rad med artikler under den, så lenge gjeldende skjermstørrelse er større enn bruddpunktet satt til md .

Nå hvis du endrer størrelsen på nettleseren din tilsvarende, bør du få resultatene du håper på, en React-app med responsive komponenter.

Vi kan til og med lage src/components/Articles/index.js fil enda bedre ved å lage en minikomponent for å vise raden med artikler. Slik det er nå, gjentas kodeblokken for å vise raden to ganger begge i <Media /> komponent for md skjermer og større enn md skjermer.

La oss følge DRY-prinsippet og lage en komponent for det:

import React from "react"
import { Media } from "../../Media"
import FeaturedArticle from "../FeaturedArticle/index"
import * as Styles from "./styles"

const articles = [...] // articles from https://gist.github.com/yomete/53be226f779d4d1ebd3ed85b8fa5672a

const ArticleGrid = ({ articles }) => (
  <Styles.Articles>
    {articles.map(article => (
      <Styles.Card>
        <img src={article.image}></img>
        <Styles.Headline>{article.headline}</Styles.Headline>
        <Styles.FooterText>
          {article.category} {article.date}
        </Styles.FooterText>
      </Styles.Card>
    ))}
  </Styles.Articles>
)

const Articles = () => {
  const featuredArticle = articles.slice(0, 1)
  const desktopArticleGrids = articles.slice(1, 4)
  const mobileArticleGrids = articles.slice(0, 4)
  return (
    <>

      <Media lessThan="md">
        <ArticleGrid articles={mobileArticleGrids} />
      </Media>

      <Media greaterThanOrEqual="md">
        <FeaturedArticle article={featuredArticle[0]} />
        <ArticleGrid articles={desktopArticleGrids} />
      </Media>

    </>
  )
}

export default Articles

La oss kjøre yarn start kommando igjen bare for å sikre at alt fortsatt fungerer som forventet. Siden din skal se ut som den nedenfor.

Konklusjon

I denne artikkelen har du sett hvordan du bygger responsive React-komponenter ved å bruke @artsy/fresnel-biblioteket. Du så også noen av fordelene som @artsy/fresnel-pakken har fremfor andre biblioteker.

Hva er noen av de responsive komponentbibliotekene du har jobbet med?

Hele koden for eksemplet bygget ovenfor kan sees på GitHub.

Plugg:LogRocket, en DVR for nettapper




LogRocket er et frontend-loggingsverktøy som lar deg spille av problemer på nytt som om de skjedde i din egen nettleser. I stedet for å gjette hvorfor feil oppstår, eller be brukere om skjermbilder og loggdumper, lar LogRocket deg spille av økten på nytt for raskt å forstå hva som gikk galt. Den fungerer perfekt med alle apper, uavhengig av rammeverk, og har plugins for å logge ekstra kontekst fra Redux, Vuex og @ngrx/store.

I tillegg til å logge Redux-handlinger og tilstand, registrerer LogRocket konsolllogger, JavaScript-feil, stacktraces, nettverksforespørsler/svar med overskrifter + kropper, nettlesermetadata og tilpassede logger. Den instrumenterer også DOM til å registrere HTML og CSS på siden, og gjenskaper pikselperfekte videoer av selv de mest komplekse enkeltside-appene.

Prøv det gratis.

Innlegget Bygg responsive komponenter i Gatsby med artsy/fresnel dukket først opp på LogRocket Blog.