How to use real data in Framer X

Pavel Laptev
Prototypr
Published in
8 min readOct 6, 2018

Framer always was different from other prototyping tools for many reasons but the major one is real data. I’ll try to show briefly how you can load and use real data in your prototypes.

Today we will make cards based on real data. The most common and efficient way to load data today is JSON format.

So, we will make some product cards. Let’s take Nike sneakers and three cards for example.

To create cards we need four keys:

  1. image — a sneakers image on transparent background
  2. product — name of the product
  3. price — obviously is a price
  4. background — is a card background, we will use a linear gradient.

To make this article shorter let’s skip the part where I explain how to make A layout in CSS (how the CSS layout is made, so here’s the code):

We start from removing all default parts in our component, even Framer ControlTypes, because we won’t use them. We have only:

  • default component size in defaultProps object,
  • render() method with layout containing a “wrapper” div,
  • a card — just one for now
  • and styles for each card element.

Plus we will use map() method to create a loop.

Use a JS object inside a component

It’s simple: just add an object in the beginning as a const variable

With the spread operator we can mix many style chunks into one object. It’s very convenient —we mix backgroundImage and styles outside the class.

👇👇👇 DOWNLOAD THIS FILE 👇👇👇

Load data from JSON using external API

Let’s take RandomUser.me API. Some code from this method we will use in next examples.

To get data from the website we will use the fetch() method, it’s the modern way to make http requests

but first things first, break down the component

line 5—11. props.userAmount —this is a cards counter (number controller) and with its help we could set the number of product cards we need to create.

state.json—React don’t have setProps(), so we will use setState() instead. We have to use setState only in React Lifecycle. Let’s call our state “json”.

interface Props {
usersAmount: number;
}
interface States {
json: any;
}

line 13. It’s our link, a place where a GET request will be sent. To define how many profiles we want to get, we will use query string ?results=number but the number we will set in the props object.

const dataURL = "https://randomuser.me/api/?results=";

line 17—25. Define default props, number of cards in particular. Also, we should create “json” state it should be an empty array.

static defaultProps = {
width: 375,
height: 600,
usersAmount: 3
};
state = {
json: []
};

line 27—35. Create a Framer control. Max cards amount will be fifteen for example.

static propertyControls: PropertyControls<Props> = {
usersAmount: {
type: ControlType.Number,
max: 15,
min: 1,
step: 1,
title: "Amount"
}
};

line 37—42. The most important part in our code is the fetch() function. We will call this method in a few places in the component lifecycle.

In the function we will pass dataURL + this.props.usersAmount

fetchJSON(jsonPath) {
fetch(jsonPath)
.then(response => response.json())
.then(data => this.setState({ json: data.results }));
}

line 46—56. As I mentioned we will use fetchJSON() in the component lifecycle methods — componentDidMount() and componentDidUpdate().

// We need this method for the very first time
// when we drag`n`drop our component from the left panel
componentDidMount() {
this.fetchJSON(dataURL + this.props.usersAmount);
}
// Compare previous and current Prop. If they are different
// we could make changes
componentDidUpdate(prevProps, prevState) {
if (prevProps.usersAmount !== this.props.usersAmount) {
this.fetchJSON(dataURL + this.props.usersAmount);
}
}

line 58–80. Render() method is the same as in the first example. Create a loop Object.map(), take keys name, email and picture from the fetched object.

Boom! Done!

👇👇👇 DOWNLOAD THIS FILE 👇👇👇

Load data from a file

This prototype will be like others, but we will use new Framer X property control — file. With this control we could load and use any file from our system.

Because we don’t have a JSON file in the initial state we need to create an empty placeholder state. To change this state (fill it) when component will be mounted or updated (through props.json) we need to check the length of the returned fetch object. If this object has a length less then 0 we will use our placeholder. Like in componentDidMount() if props.json is empty we will show warning message in console.

componentDidMount() {
if (this.props.json && this.props.json.length > 0) {
this.fetchJSON(this.props.json);
} else {
console.log("%cPlease include JSON file", "background:#f45; color:#fff");
}
}

The same check method in render(): If we have a JSON file → do this, if not → do that.

<div style={this.props.json && this.props.json.length > 0 ? wrapStyle : errorWrapStyle}>

And the file Framer control for loading external files.

static propertyControls: PropertyControls = {        
json: {
type: ControlType.File,
allowedFileTypes: ["json"],
title: "JSON"
}
};

Load data, design-components and overrides

And the last part is how we could mix design-components and real data. To make it possible we will use props.children. With props.children we can pass design component or code components into another code components.

In my opinion is not a good approach — to use design components when you have a deal with text layers because Framer X don’t have relative positioning (Framer guys please write this feature into your backlog) it means that we couldn’t make a “true flexible” component.

There is some advantages over code components —it’s the speed. We can make design component much faster then code components, test multiple modifications.

What we will do?

We will do a wrap component, this component can create a number of cards based on json object length (loaded from the file)+ we will have overrides inside the component which we will use in cards (design-component). I think this is very convenient — to use overrides instead of code script which will go through children and find matches like— text, image, background; furthermore I didn’t find how to change a text inside a text layer using props.children. Overrides looks better then this.props.children[0].props.chilfren[0].props.children[2].background

This is our scheme:

In this component we won’t to load a JSON by fetch() method, we will use a JSON file as a local file. To do this we need to rename cards-data.json into cards-data.ts and create an exportable const inside. After that move this file into the “code” folder.

And the component code. What I like here is that component is really simple

Our code consist of three parts — dependencies (or imports), class and overrides.

line 1–10. Pretty usual part but line 3 is data obj import

import { cardsData } from "./data/cards-data";

inside interface Props we create itemsAmount prop with this property we will control a number of cards inside the component.

Second part. It’s a part where we create our class, let’s name it DesignCompAndJSON.

line 14–18.

line 21–29. Here we create itemsAmount controller where max value is the same as data obj length. Also, we mix all Stack controls to the component controls.

line 31–37. In render() method we create an array from itemsAmount prop and iterate linked children through the map() method.

line 40–49. Third part starts here. Here we create a counter; we wouldn’t make a random function, instead, we will create a counter function and each time we use overrides, we will increment the counter variable, if the variable is bigger than our data obj, then we will reset it to avoid errors.

line 57–71. The last part is Overrides. We made overrides for each layer in our design component — image, product name, price and background gradient.

This overrides will be available for all design components from the sidebar “code” section .

This is it. Now we can override all elements in our card and choose which overrides we want to use

Link different designs.

Thank you! I hope this is useful

Yours sincerely,

Pavel a.k.a. “I maked these” Laptev

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Responses (5)

What are your thoughts?