Search code examples
javascriptreactjsgraphqlgatsbystrapi

Gatsby React query GraphQL


I am trying to help a friend who is building some site combining Gatsby and Strapi. I have null experience with both...

The frontend it's made with React and it's calling the backend with GraphQL.

He has two components: <EstateSearch> and <FeaturedEstates>. <EstateSearch> should fetch data from backend and then filter it and hydrate <FeaturedEstates> component.

Usually I would use React Context API to store fetched data across components, but I have been reading here that queries can be triggered at build-time and at run-time. But in their example they use Axios library to get data from outside, not from backend.

The code

EstateSearch.js

import React, { useRef, useState } from "react";
import { graphql } from 'gatsby';
import './style.scss';

export const query = graphql`
  query inmuebles {
    allStrapiInmuebles(filter: {dormitorios: { eq: 2}}) {
      edges {
        node {
          id
          nombre
        }
      }
    }
  }
`;

const EstateSearch = props => {
  const [ isRent, setIsRent ] = useState(true);
  const [ isSale, setIsSale ] = useState(false);
  const state = useRef('');
  const [ cities, setCities  ] = useState([]);
  const city = useRef('');
  const zone = useRef('');
  const rooms = useRef(0);
  const bathrooms = useRef(0);
  const priceFrom = useRef(0);
  const priceTo = useRef(0);

  console.log(props.data);

  return (
    <div className="estateSearch">
      <h3>Estate Search</h3>
      <form onSubmit={submitForm}>
        <button
          type="button"
          className={`rentButton ${!!isRent ? 'activeButton' : ''}`}
          onClick={e => handleButton('rent')}
        >Alquiler</button>
        <button
          type="button"
          className={`saleButton ${!!isSale ? 'activeButton' : ''}`}
          onClick={e => handleButton('sale')}
        >Venta</button>

        <select className="city" ref={zone}>
          ...
        </select>

        <select className="city">
          <option value="" >Lorem</option>
          <option value="">Ipsum</option>
        </select>

        <select name="city" className="city" ref={city}>
          <option value="" >City</option>
          <option value="">Lorem</option>
        </select>

        <div className="rooms">
          <input type="number" name="rooms" min="0" placeholder="Rooms" ref={rooms} />
        </div>
        <div className="bathroom">
          <input type="number" name="bathroom" min="0" placeholder="Bathrooms" ref={bathrooms} />
        </div>
        <div className="priceFrom">
          <input type="number" name="priceFrom" min="0" placeholder="Price from" ref={priceFrom} />
        </div>
        <div className="priceTo">
          <input type="number" name="priceTo" min="0" placeholder="Price to" ref={priceTo} />
        </div>
        <div className="search">
          <input type="submit" value="Search" className="search" />
        </div>
      </form>
    </div>
  );

  function handleButton(type) {
    if (type === 'rent') {
      setIsRent(true);
      setIsSale(false);
    } else {
      setIsRent(false);
      setIsSale(true);
    }
  }

  function submitForm(e) {

    

    e.preventDefault();
  }
}

export default EstateSearch;

FeaturedEstates.js

import React from 'react'
import { Link, graphql } from 'gatsby'
import Layout from '../components/layout'
import Cover from '../components/Cover'
import FeaturedEstates from '../components/FeaturedEstates/featuredEstates'
import ServicesItems from '../components/ServicesItems/services'
import EstateCard from '../components/EstateCard/estateCard'

const IndexPage = ({ data }) => (
  <Layout>

    <Cover />

    <FeaturedEstates>
      {data.allStrapiInmuebles.edges.map(document => {
          const inmueble = document.node;
          let precio;
          let operacion;
          
          switch (inmueble.operacion) {
            case 'Alquiler':
              precio = `$${inmueble.precioAlquiler}`;
              operacion = inmueble.operacion;
              break;
            case 'Venta':
              precio = `U$S${inmueble.precioVenta}`;
              operacion = inmueble.operacion;
              break;
            default:
              precio = `$${inmueble.precioAlquiler} / U$S${inmueble.precioVenta}`;
              operacion = 'Alquiler / Venta';
          }

          return (
            <li key={document.node.id}>
                  <EstateCard 
                      key={inmueble.id}
                      imagen={inmueble.imagendestacada.publicURL}
                      rooms={inmueble.dormitorios} 
                      bathrooms={inmueble.banios}  
                      garage={inmueble.estacionamiento} 
                      area={inmueble.superficieConstruida}
                      titleBar={inmueble.nombre}
                      estateTipe={inmueble.tipo}
                      transactionTipe={operacion}
                      refCode="0178"
                      priceCard={precio}
                      Button= {<Link to={`/${inmueble.id}`}>Ver Mas</Link>}
                    />
              </li>
          );
      })}  
    </FeaturedEstates>

    <ServicesItems /> 

  </Layout>
)

export default IndexPage;

export const query = graphql`  
query IndexQuery {
  allStrapiInmuebles {
    edges {
      node {
        id
        nombre
        dormitorios
        banios
        superficieConstruida
        operacion
        tipo
        estacionamiento
        precioVenta
        precioAlquiler
        imagendestacada {
          publicURL
        }
      }
    }
  }
}

`

I guess I will have to use Context API anyway, but how should I fetch data from the same Gatsby server when some user searches something?


Solution

  • You won't be able to access Gatsby's store in production. As a static site generator it produces static files :)

    If you really need live data interaction in runtime you will need to query against live server just like a regular react app does.