Skip to content

Instantly share code, notes, and snippets.

@BrunoQuaresma
Last active January 18, 2022 01:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BrunoQuaresma/0236aff64dc44795f19994cbc7a07db6 to your computer and use it in GitHub Desktop.
Save BrunoQuaresma/0236aff64dc44795f19994cbc7a07db6 to your computer and use it in GitHub Desktop.

useQuery

The useQuery() is a React hook used to run FQL queries.

Install

Wrapper your app with the <FaunaProvider> component passing the client like bellow:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import faunadb from "faunadb";
import { FaunaProvider } from "./react-faunadb-hooks";

const faunaClient = new faunadb.Client({
  secret: 'your-secret'
});

ReactDOM.render(
  <FaunaProvider client={faunaClient}>
    <App />
  </FaunaProvider>,
  document.getElementById("root")
);

How to use

The useQuery() has the following structure:

useQuery(
  expression: FaunaExpression,
  options: {
    runNow: boolean,
    params: Object,
    database: ?String
  }
): {
  data: Array || Object,
  loading: boolean,
  error: Error,
  runQuery: (params: Object) => Promise<Array || Object>
}
  • runNow: Use trueif you want to run the query right after the mount. The default is false.
  • params: If you need to pass dynamic values to the query.
  • database: Used to access child databases. Left it blank if you want to access the root database.

Fetching indexes using FQL Syntax

const AllIndexes = fql`
  Map(
    Paginate(
      Indexes()
    ),
    Lambda(x => Get(x))
  )
`;

function App() {
  const { data: indexes } = useQuery(AllIndexes, { runNow: true });

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>
    </div>
  );
}

Fetching indexes using Function Composition

const getAllIndexes = (q, params) => {
  return q.Paginate(q.Indexes());
};

function App() {
  const { data: indexes } = useQuery(getAllIndexes, { runNow: true });

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>
    </div>
  );
}

Calling a query

const CreateDatabase = fql`
  CreateDatabase($database)
`;

function App() {
  const { runQuery: createDatabase } = useQuery(CreateDatabase);

  const onSaveClick = () => {
    createDatabase({ 
      $database: { name: 'New DB' }
    })
   .then(() => {
      showSuccessMessage()
      resetForm()
    })
    .catch(error => {
      console.error(error)
      showErrorMessage(error.message)
    })
  }

  return (<>...</>);
}

export default App;

Running a query in child database

const AllClasses = fql`
  Map(
    Paginate(
      Classes()
    ),
    Lambda(x => Get(x))
  )
`;

function App() {
  const { data: indexes } = useQuery(
    AllClasses,
    {
      runNow: true,
      database: 'childA/childB'
    }
  );

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>
    </div>
  );
}

Using cache

Cache can be used passing a cache param inside the options. The supported cache options are:

  • key: The cache key.
  • sync: Use false if you don't want to sync the data on each mount. The default is true.
  • manual: Use truewhen you want to set/update the cache manually. Recommended for mutation queries like creates, updates and deletes.

Basic cache

const AllIndexes = fql`
  Map(
    Paginate(
      Indexes()
    ),
    Lambda(x => Get(x))
  )
`;

function App() {
  const { data: indexes } = useQuery(
    AllIndexes,
    {
      runNow: true,
      cache: { key: 'indexes' }
    }
  );

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>
    </div>
  );
}

Running a query only once

const AllIndexes = fql`
  Map(
    Paginate(
      Indexes()
    ),
    Lambda(x => Get(x))
  )
`;

function App() {
  const { data: indexes } = useQuery(
    AllIndexes,
    {
      runNow: true,
      cache: {
        key: 'indexes',
        sync: false
      }
    }
  );

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>
    </div>
  );
}

Updating cache after mutation

After run a query the promise will return the data and some cache helpers.

  • setCacheValue: Set a new cache value for the specified key.
  • cacheData: The current cache value for the specified key.

Ps.: Remeber to use manual: true to update manually the cache.

const AllIndexes = fql`
  Map(
    Paginate(
      Indexes()
    ),
    Lambda(x => Get(x))
  )
`;

const CreateIndex = fql`
  CreateIndex($index)
`;

function App() {
  const { data: indexes } = useQuery(
    AllIndexes,
    {
      runNow: true,
      cache: {
        key: 'indexes',
        sync: false
      }
    }
  );

  const { runQuery: createIndex } = useQuery(CreateIndex, {
    cache: {
      key: 'indexes',
      manual: true
    }
  });

  const handleSubmit = event => {
    event.preventDefault();

    createIndex({
      $index: { name: inputValue }
    })
    .then(({ data, setCacheValue, cacheData }) => {
      cacheData && setCacheValue(cacheData.concat(data));
    })
    .catch(console.error);
  };

  if (!indexes) return <>Loading...</>;

  return (
    <div>
      <h1>Indexes</h1>
      <ul>
        {indexes.map(index => (
          <li key={index.name}>{index.name}</li>
        ))}
      </ul>

      <form onSubmit={handleSubmit}>
        <label>New index</label>
        <input type="text" onChange={...} />
        <button>Save</button>
      </form>
    </div>
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment