Skip to main content

Pass client state to a Netlify function

Disclosure: I am currently on the Product team at Netlify.

Awhile back I built a drawing idea generator, which pulls a random Unsplash image for you to draw. I wanted to add filters, so that people could refine the result by subject and/or orientation. I use a Netlify serverless function to fetch from the API, so I needed to pass client state—i.e. the user’s filter configuration—into the Netlify function. Enter query parameters!

HTML

First, people need to be able to select their filters! I added a couple <select> elements to the markup, using Unsplash’s API values for each <option> value:

<label for="topics">Topic</label>
<select id="topics" aria-describedby="topic-desc">
  <option value="any" default>Any</option>
  <option value="Jpg6Kidl-Hk">Animals</option>
  <option value="rnSKDHwwYUk">Architecture</option>
  ...
</select>

<label for="orientation">Orientation</label>
<select id="orientation">
  <option value="any" default>Any</option>
  <option value="landscape">Landscape</option>
  <option value="portrait">Portrait</option>
  <option value="squarish">Squarish</option>
</select>

“Any” is not an accepted value in the API, but I provided that value here so I wouldn’t have to handle conditional logic for undefined filters. Unaccepted values are essentially ignored in requests to the API.

Client-side JavaScript

Per my client-side scripts, clicking on the “Try another photo” button calls a function fetchPhoto that then invokes my photos.js serverless function.

I updated fetchPhoto such that it now reads the values from the filter <select>s, and passes those to the serverless function as query parameters:

const fetchPhoto = async function (delay) {
  const topicsValue = document.getElementById('topics').value,
        orientationValue = document.getElementById('orientation').value,
        functionWithParams = `/.netlify/functions/photos?topics=${topicsValue}&orientation=${orientationValue}`;

  let response = await fetch(functionWithParams).then(handleErrors).then(response => response.json());

  ...
}

Serverless function

Now I can reference those in my serverless function, aka photos.js:

exports.handler = async function (event) {
  const API_KEY = process.env.UNSPLASH_API_KEY,
        photoAPI = `https://api.unsplash.com/photos/random?content_filter=low&client_id=${API_KEY}`,
        paramTopics = event.queryStringParameters.topics,
        paramOrientation = event.queryStringParameters.orientation,
        photoAPIWithParams = `${photoAPI}&topics=${paramTopics}&orientation=${paramOrientation}`,
        response = await fetch(photoAPIWithParams),
        data = await response.json();

	return {
		...
	}
}

Here I’m using event.queryStringParameters to retrieve the parameters I passed in from client-side JS. queryStringParameters returns an object, so I’m defining a variable for each key in the params object, then appending it to the API request URL.

And voila! Sketchers can now choose a topic and/or orientation, click “try another photo”, and receive an appropriate image:

The filters are set to the animals topic and squarish orientation. The returned photo is a square image of two red-capped birds, one of whom is in flight.

This isn’t the only way to use query parameters! You could also access them in your return statement, if for example you wanted to print these values for the user.

To check out this update in context of the project, you can explore my code on Github.

Responses

My blog uses Webmentions. Responses from sites which likewise support Webmentions, such as Twitter or people’s personal sites, will show up here.

  • Reply from Cody on

    @melanie that’s a slick trick! I dig it.