We know from the previous video that
Client Components are hydrated in the browser.
When we load the page,
the ShareLinkButton is first rendered
as HTML on the server,
and then rendered again in the browser,
this time adding any interactive functionality.
You may wonder why we need to send to the browser
the full JavaScript code for this component.
Since all we do when the user clicks the button
is execute the "handleClick" function,
in theory we could send to the browser
only the code for that function.
Why does React need to re-render
the whole component?
The reason is that most of the time
we'll also want to do other things in a component,
like updating the user interface.
For example, when the user clicks
the "Share link" button,
we'll want to display a message,
telling the user that
the link was in fact copied to the clipboard.
To do that, we'll also need to keep some state,
to know when to display the "link copied" message.
In React, we can create a state variable
with the "useState" hook.
It will return an array,
where the first element is our state variable,
let's call it "clicked",
and the second element is a function
that we can use to update the variable value.
We'll get this array by calling "useState",
that we can import from the "react" module.
We can pass an initial value
for our state variable,
in this case we want "clicked" to be false.
Now we can use this variable to decide
what text to display as the button label.
If "clicked" is true then we
can say "Link copied!",
while if it's false we'll show
"Share link" as before.
Let me log this "clicked" variable to the console,
so you can see its value whenever
this component is rendered.
I'll show you the server logs as well,
and go and reload the page.
You can see that, initially, "clicked" is false,
because that's the value we passed to "useState",
and it's the same both on the
server and in the browser.
Now, we'll want to change that value
when the user clicks the button,
so in "handleClick".
Here we can call the "setClicked" function,
that was the second element returned by useState,
passing true as the new value,
since the user just clicked the button.
This will cause our component to re-render
with "clicked" set to true,
which means the button text should
change to "Link copied!".
But we don't want it to say "Link copied" forever.
Let's use "setTimeout" to reset it after a while.
We can set "clicked" back to false,
after say 1500 milliseconds,
that means one and a half seconds.
Let's see how it works now, if
we start from scratch again.
Initially, "clicked" is always false.
But if we go and click the button,
the text changes to "Link copied!",
but only for a short while,
then it goes back to "Share link".
In the console, you can see that
right after we clicked the button
the component re-rendered with "clicked" as true,
and later, once the timeout
function was triggered,
it rendered again, with "clicked" back to false.
Of course, the component only
re-rendered in the browser,
not on the server, where it's only
used to generate the initial HTML.
Anyway, we're now briefly showing
"Link clicked!" to the user,
so they know that clicking
the button did something.
At this point, all that's left to do is
actually copy the link to the clipboard,
that is the whole point of this button.
The "navigator" global object
has a "clipboard" property,
that we can use to access the system clipboard.
To copy something into it we can
call the "writeText" method.
Now, we want to pass the page URL,
that will be the same one visible
in the browser address bar.
We can get that value in JavaScript
by using the "window.location" object.
Its "href" property will be the URL.
Ok. Let's save, and see if this works.
If we click this button, it says "Link copied!".
What I'll do is open a new text file
and press Command+V to paste
what's in the clipboard.
You can see that it is in fact the right URL.
Let's test it with a different review,
like "Stardew Valley" for example.
And if I press Command+V
it copied the URL for that other page.
Good. Our "Share link" button is fully working.
And this is a simple example of
interactive functionality,
that only works in Client Components.