Designing a Switch in Framer, Part II
A crash course in code components with the new Framer X API.
Introduction
Welcome to the second part of the Designing a Switch in Framer, a short tutorial series where we’ll be creating and using a code component in Framer X.
In Part I, we:
- Set up our Framer X workspace.
- Created a code component for our Switch
- Defined our component’s state logic
- Presented our component’s state using animations
In Part II, we’ll:
- Add props to our Switch, so that we can set its state from outside of the component
- Add property controls for our Switch, so that we can set our component’s props through Framer’s user interface
If you’re new to Framer X (or to React), then this tutorial is a great introduction to working with code. I’d recommend completing Part I before working through this tutorial.
Getting Started
We’ll be making this project with Framer X. If you don’t have it already, download a copy and enjoy the 14-Day trial.
If you’d like to pick up where we left off, click here to download the finished project from Part I of this tutorial.
Defining our component’s props
While our switch is already working, our component is so far a closed system: it has no way of getting information from other components. While our switch is switching, it can’t be switched!
In order to make our switch more social, we’ll need to use props. As we discussed in the last part of this tutorial:
Props are data that comes from the outside world. If a component is a function — and it technically is — then props is an argument passed to that function. If a component is a pizza, then props are the pizza order — toppings, crust, etc. Learn more about components and props.
Adding our first prop: isOn
For our component’s first prop, we’ll add a prop that will let us set the Switch’s initial state to on or off. Our component’s state is stored as isOn
and we’ll use the same name for our prop.
First, let’s add isOn
to our component’s default props.
- Below our component, add a set of
defaultProps
as shown below. - Create a default prop for
isOn
and set it tofalse
.
import * as React from "react"
import { Frame } from "framer"export function Switch(props) {
...
}Switch.defaultProps = {
isOn: false
}
Next, let’s tweak our component so that it uses this prop to set the component’s initial state.
- Find the
setState
hook at the top of our component. - Replace the value of
isOn
withprops.isOn
.
const [state, setState] = React.useState({
isOn: props.isOn,
})
We can test that it’s working by changing the value of defaultProps.isOn
between true
and false
. When we reload our Preview, we should see that the component starts on or off depending on this value.
Adding a property control
Next, let’s add a property control. In Framer X, property controls give us the means to set our props from the canvas. In our case, we’ll create a little switch for our switch, so that we can set props.isOn
from the canvas.
- At the very top of our project, add
ControlType
andaddPropertyControls
to the list of imports from theframer
library. - Below our component’s
defaultProps
, useaddPropertyControls
as shown below to define ourisOn
property control.
The
addPropertyControls
is a function that takes two arguments: a component and an object of property controls. In this object, we define each control under the name of the prop that we want to control. We won’t go deeper into the details here, so be sure to bookmark our guide to property controls.
import * as React from "react"
import { Frame, addPropertyControls, ControlType } from "framer"export function Switch(props) {
...
}Switch.defaultProps = {
isOn: false
}addPropertyControls(Switch, {
isOn: {
type: ControlType.Boolean,
title: "On",
defaultValue: false,
}
})
Now let’s jump back to our canvas to see the results.
Unfortunately, flipping the value on or off won’t have any effect on our switch on the canvas. However, if we create some copies of our component (by holding the Option
key and dragging the instance), then we’ll see that the copies are respecting the prop. What’s going on?
The problem is that while our props.isOn
sets the component’s initial state, it doesn’t control the state beyond that. The real logic we want is something like:
- When the switch first mounts, use
props.isOn
to set the initialstate.isOn
. - If
props.isOn
ever changes, and if the change is different from our currentstate.isOn
, then setstate.isOn
to the newprops.isOn
.
Adding an effect
To solve this problem, we’re going to need to use a second React hook, useEffect
.
- In our component, find a space just after our
useState
hook. - Add the
useEffect
hook from the snippet below.
const [state, setState] = React.useState({
isOn: props.isOn,
})React.useEffect(() => {}, [])
A useEffect
hook is a function that takes two arguments: a function and an array of variables. We call the function an effect and we call the array of variables the effect’s dependencies. It works like this:
- React will call the effect immediately after the component’s first render.
- Every time the component renders, React will compare the values of its dependencies against their values from the previous render.
- If it finds any changes, React will call the effect again.
In our case, we want the effect to run when props.isOn
changes, so let’s add that to the effect.
React.useEffect(() => {}, [props.isOn])
When the effect runs, we want to compare the values of state.isOn
and props.isOn
. If they’re different, then we want to update state.isOn
to match props.isOn
.
React.useEffect(() => {
if (state.isOn !== props.isOn) {
setState({
isOn: props.isOn
})
}
}, [props.isOn])
Let’s return to the canvas and see where we’re at.
Ok, that’s better!
Our finished component
Let’s take another look at our component.
Just like last time, we’ll walk through each part that we’ve added. Anything not covered below was code from Part I, and you can read about it there.
Line 2
: We added addPropertyControls
and ControlType
to the list of imports from the “framer”
library.
Line 6
: We changed our setState
function to use props.isOn
to set the component’s initial state.
Lines 9 – 15
: We added a useEffect
hook that runs when our component receives a different value for props.isOn
and, if necessary, updates state.isOn
to match props.isOn
.
Lines 60 – 62
: We added a set of defaultProps
, ensuring that our component will always have a value for props.isOn
.
Lines 64 – 70
: Finally, we added a set of property controls to our component. At the moment, our property controls only include one control for the isOn
prop.
To download the finished project, click here.
Next step: Interactions
In this tutorial, we learned about how to get information into our component from the outside world through props. We also added our first property controls, so that we could set our props from the canvas. We also learned to use a useEffect hook to control the logical relationship of props and state.
However, while our switch can now receive information from the outside world, it still has no way of sharing information with other components. In other words, our switch can be switched, but it can’t switch anything else!
In the final part of this three-part series, we’ll give our component a new prop named onValueChange
and we’ll learn to use it with overrides to control other parts of our prototype.
If you liked this article, please do 👏 let 👏 me 👏 know!