FAQ: The State Hook - Use State Setter Outside of JSX

This community-built FAQ covers the “Use State Setter Outside of JSX” exercise from the lesson “The State Hook”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn React

FAQs on the exercise Use State Setter Outside of JSX

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

Interestingly, it appears that the way the code is written currently doesn’t work exactly as desired. We start with an empty string as the initial state of the input field. That’s fine. If we try to type in a letter or any character other than a digit, the validPhoneNumber denies this change via the regex check. This is also as intended. Once we start entering digits, the regex /^\d{1,10}$/ matches the digits and the field starts showing the new phone number. If we try to delete the digits, it seems to work BUT we can’t delete the first digit. Suppose we start typing in 3219 and then decide to change the phone number, we can get rid of the 219 but not the 3. If we try to delete the first digit, the validPhoneNumber won’t let us make this deletion as an empty string will fail the regex test. So, as things stand currently, we can’t delete/edit the very first digit of the phone number.

9 Likes

also curious the answer for this :rofl:

As things stand, once we start typing in a phone number, we can’t completely wipe out the number because an empty string will fail the regex test. So, the regex needs to be corrected.
As a workaround, instead of using the backspace to try and edit the number, we can use the arrows or mouse click to move the cursor to the right position and then use backspace to edit the first digit. So, if the number is 3219 and we want to edit the first digit, we can use the arrows (or mouse) to move the cursor between 3 and 2. Then, we can delete the 3. But, that will only work if at least one other digit of the previous number still remains. Basically, the issue is once we start typing the number, the existing regex won’t allow us to completely delete the whole phone number. We can tweak the regex to allow this.

I have a question on the object destructuring… so in the example…it shows us const handleChange = (event) => { const newEmail = event.target.value; setEmail(newEmail); }
then it simplifies it with
const handleChange = (event) => setEmail(event.target.value);
ok I understand this…
but then using object destructuring it says you can do this also…
.const handleChange = ({target}) => setEmail(target.value);
so my question is…what happened to the word event and how does it fit now? and why does target get the curly braces around it now too? why dont we have to use event anymore?

4 Likes

When you interact with a page, you may click on something or press a key or do something else. All these interactions are considered events. When an event happens, an event object is also created. This object carries detailed information about exactly what happened, which element was targeted, what was clicked or typed or selected and so on. You can read more about the methods and properties contained in these event objects: firstlink and secondlink .

In the snippets you mentioned, we have defined an event handling function thus:

const handleChange = (event) => { 
    const newEmail = event.target.value;  
    setEmail(newEmail);
}

This is an arrow function where event is just the parameter of this function. There is nothing special about the parameter name event. We could have picked a different parameter name. We could have named our parameter usefulObject or soemthing else in which case our function would look like
const handleChange = (usefulObject) => { and we would use the parameter name usefulObject within our function body. However, since we are defining an event-handling function and we expect that once an event happens, an object is going to be passed to our function, so we should pick our parameter’s name to be something suitable. So, most of the time you will see that people choose either event or e as the parameter name. Instead of picking parameter names randomly, it is a good idea to pick names which are meaningful. It makes for more readable code both for the programmer and anyone else reading the code. So, event is the name we picked for the parameter of our handleChange function.
When an event happens, an event object is created and is sent to the event handling function. One of the properties contained in the object is target. You can read about it briefly in the links above. So, in the snippet above, the object is assigned to our parameter event. Then, in the function body we use event.target.value; to get the relevant information (the new email in this example) from that object.

The other snippet you mentioned is:

const handleChange = ({target}) => setEmail(target.value);

One of the motivations behind this version is that the event object carries a lot of information, but for this particular function, we really are only interested in the target property contained in that object. So, why not skip intermediate steps and just get at that property immediately. For this we are using something called Destructuring Assignment. You should have a look at this:

The links will explain it better than me, but here is what is happening in this particular snippet.

const handleChange = ({target}) => setEmail(target.value);

The parameter name is supposed to go in between the parentheses ( ) to the left of the arrow. But, we really aren’t interested in the whole object that is going to be assigned to our function’s parameter. So, we basically say why bother naming the parameter? Why should we bother naming our parameter event when we really aren’t interested in the whole object? Instead we just use the curly braces (like so ({ }) => to signify that we are going to be passed in an object but we see no point in giving this object a name. Then, we specify which property(ies) of the object we really care about. In our case, it is the target property contained in the object. So, instead of ({ }) => we now write ({ target }) => This basically finds the target property of the object passed in and assigns it to a variable called target. Within our function body, we can simply use the word target to do whatever we want (in our example we do setEmail(target.value);).

Suppose we wanted to extract the target property from the passed in object but give it a name of our choice (let’s say we want to use the name targ). We could do something like
const handleChange = ({target: targ}) => setEmail(targ.value);

This basically gets the value of the target property of the object passed in and then saves that value to a variable called targ. In our function body, we can now use targ to work with the relevant data.
Have a read of the first link about Destructuring assignment. It has many examples and does a much better job of explaining what is going on.

13 Likes

Are the props in the JSX order specific? I kept getting an error for not having the variables in curly braces but I swapped the order around and it worked.

input value={phone} onChange={handleChange} id=‘phone-input’ /

vs

input id=‘phone-input’ value={phone} onChange={handleChange} /

If order isn’t specific this is extremely annoying.

3 Likes

I don’t think that the attributes have to be in a specific order.

Sometimes codecademy makes me want to punch myself in the face.

4 Likes

The specific order is annoying, I thought I was wrong lmao. However, in React, the specific order doesn’t really matter.

1 Like

That should be reported (if it’s possible, no idea), the order doesn’t matter. I kept getting the same error.

Thank you so much for explaining the lifestory of “event”, why is it called “event” and why you should name it “event” but that’s not really what he asked…

change it to /^\d{0,10}$/ and it will work, I’m honestly confused as to whether they missed it or they made it like that so the user can’t enter a 0 length phone number but still there are other ways to make the user enter at least one digit.

That was a great explanation. thanks a lot

1 Like

I am having trouble seeing the point of this exercise or it’s application. Why would you use state setters outside of JSX?

I can see that the code only allows you to put in numbers but why can’t you delete the first digit if say you’ve made a mistake?

1 Like

great great explanation! thank you!

1 Like

Hi!

How does it work with an onClick event listener? The exercise is using an onChange event listener with all those weird new things such as event.target.value that I see for the first time (the exercise does’t event explain anything about it).

I did the following name switcher based on what I’ve learned in the previous exercise:

function NameSwitcher(){
 
  const defaultName = 'Irma';
  const newName = 'Alan';
  const [name, setName] = useState(defaultName);

  return (
      <div>
        <button onClick={name === defaultName ? ()=>setName(newName) : ()=>setName(defaultName)}>Switch name</button>
        <p>{name}</p>
      </div>
    );
};

My question: How can I use the state setter outside the JSX and get the same result ?

Bit annoying but I couldn’t get past task 2 except by adding an extra space before the input’s closing tag. The error message was completely wrong

Hi All,

Where I can find explanation of DEFAULT use case when you declare function comp…

export default function PhoneNumber() {.....

Maybe I missed somewhere or it appeared and I have no understanding of DEFAULT use case during declaration of
function components.

Your guidance highly appreciated. :pray:

Hi all,
If you are reading and have in mind to replay to help me.
Thanks you are awesome.
I just surfed google and read about this problem.
Apparently it was all about named and default exporting fun/comp/class/ etc.
I understood that default enables to import without curly braces

export function myNamedExpo () {}
import {myNamedExpo} from 'someDirectory'

export default myDefaultExpo () {}
import myDefaultExpo from 'someDirectory'

Overall it does not affect the code but helps to improve your code readability.
If anything missed or misunderstood please reply and give your guidance.
Thanks :pray:

1 Like