What you'll learn:
We’ve got the slider working now, but our code is starting to get long and messy. Let’s clean it up and learn an important concept about React.
I’ve told you that the key difference between JSX and HTML is that in JSX we can define custom tags.
The <Frame>
is a custom tag defined in framer we imported and used.
Now let me show you how to define a custom tag, that is, a React component.
We’ve already done this with the App
function! App
is a React component, remember?
In fact, a React component is just a function.
Let's write a new React component. It will be just a function, but the name starts with an uppercase letter. We can make it a printer that prints out snapshots of the UI.
function Skinny() {
return
}
Remember this picture?
Now we have the component here as the printer and React as the person flipping the pages. We are going to learn more about this picture in the modules of react states, but at this point just remember that a React component is a printer that prints out something.
<Skinny>
componentLet's see what snapshot of the UI we are going to return from the Skinny
function. We can copy and remove this portion of our code because this is Skinny.
<Frame width={290} height={320} position="relative" background="transparent">
<Frame
background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fskinny-portrait.png)"
width={290}
height={290}
borderRadius={150}
/>
{/* Cheek */}
<Frame
background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
width={79}
height={67}
left={155}
top={135}
animate={animationControls}
/>
</Frame>
Instead of all these <Frame>
tags we can replace it with <Skinny/>
.
<div ...>
<Skinny/>
<Frame
width={280}
height={15}
borderRadius={30}
backgroundColor="white"
position="relative"
>
...
</Frame>
...
</div>
Inside our function Skinny
, we can paste what we cut.
function Skinny() {
return
;<Frame width={290} height={320} position="relative" background="transparent">
<Frame
background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fskinny-portrait.png)"
width={290}
height={290}
borderRadius={150}
/>
{/* Cheek */}
<Frame
background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
width={79}
height={67}
left={155}
top={135}
animate={animationControls}
/>
</Frame>
}
However, we get an error called Invariant Violation
, which is quite a common source of error. When we are pasting something for the return
, we don't want the return
on a separate new line because it will be interpreted as if you want to return nothing. All we have to do is make sure a piece of our code is in-line with the return
.
function Skinny(){
return <Frame
width={290}
height={320}
position="relative"
background="transparent"
>
...
}
Unfortunately, we have a new ReferenceError
now, but let's worry about that later. Right after we save the file, the editor adds a pair of parentheses around what we pasted, so that we can put our tags underneath the return
. The parentheses mean we are going to return everything inside the brackets.
function Skinny(){
return(
<Frame
width={290}
height={320}
position="relative"
background="transparent"
>
...
)
}
We still get an error because animationControls
is not defined in our function Skinny
nor in the top level, outside the function. However, for now let's just comment animate={animationControls}
out.
function Skinny(){
return (
...
<Frame
background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
width={79}
height={67}
left={155}
top={135}
// animate={animationControls}
/>
...
)
}
<Slider>
componentNow let’s do the same thing to our Slider! Select, copy, and remove (same as cut) the slider frames. We'll put a single <Slider>
tag underneath <Skinny>
.
<div ...>
<Skinny />
<Slider />
</div>
Defining our Slider
function or component,
function Slider() {
return (
<Frame
width={280}
height={15}
borderRadius={30}
backgroundColor="white"
position="relative"
>
<Frame
size={60}
borderRadius={30}
center="y"
backgroundColor="white"
shadow="0 1px 5px 0 rgba(0, 0, 0, 0.25)"
drag="x"
dragConstraints={{ left: 0, right: 220 }}
dragElastic={false}
dragMomentum={false}
onDrag={handleDrag}
/>
</Frame>
)
}
The same error for animationControls
in Skinny
happens to handleDrag
in our slider because it isn't defined in this function or the top level. Let's just comment it out as well.
function Slider() {
return (
...
<Frame
size={60}
borderRadius={30}
center="y"
backgroundColor="white"
shadow="0 1px 5px 0 rgba(0, 0, 0, 0.25)"
drag="x"
dragConstraints={{ left: 0, right: 220 }}
dragElastic={false}
dragMomentum={false}
//onDrag={handleDrag}
/>
</Frame>
)
}
Although our slider and our picture are disconnected and don't work, the code looks a lot better.
It’s very easy to see the structure of our App
component.
It consists of a <div>
, a <Skinny>
tag and a <Slider>
tag.
If we want to do something about Skinny
, we know we can just look at and edit the Skinny
component, not anywhere else.
This demonstrates an important aspect of working with React. We are always making components. A component is made up of other components that consist of even smaller components.
You want to keep components small. And you want to keep your code tidy. This is a really good habit to have.
In our next post, we'll learn about communicating between two components. In our case, Skinny
and Slider
.