FAQ: The State Hook - Lesson Review

I think its extremely confusing because of the wording…

you have to think in terms of the previous state’s “new task” (which is technically the old/first input i.e. the title) vs the new “new task” which is the new task including both the first input (title) and the second input (details) (?)…so it’s not a “new task” per se but an additional detail of the same task. That’s why it was so confusing at first.

Is it correct to assume that it would be much easier to understand the whole thing, if they re-wrote the code using some reference to “taskTitle” and “taskDetail” instead of using just “newTask”?

you can and it will work but as mention in lesson it is a safe practice , you can review it below

" Note: We can just call setCount(count +1) and it would work the same in this example… but for reasons that are out of scope for this lesson, it is safer to use the callback method. If you’d like to learn more about why the callback method is safer, this section of the docs is a great place to start."

same problem here, this whole chapter on hooks is an absolute piece of ■■■■, not only do they waste your time learning class components, you dont learn it in depth enough so that you can then take a class component and transform it on a functional component. Its garbage.

1 Like

100%, I was enjoying this course until up to this section, it’s absolute garbage, thankfully I could resort to Youtube to learn a lot more about hooks and just ignore this garbage lesson. I’m really angry at it to be honest.

2 Likes

I am doing the Full Stack '21 course. This was the first time I have felt so confused and overwhelmed. I did not understand anything. Instructions were full of waffle and failed to teach me anything. Sadly this was a total waste of time and I will have to research hooks myself to learn this concept.

2 Likes

Hello all,

I have written out the code for this exercise and cannot figure out why I am getting an error.

// appFunction.js
import React, { useState } from "react";
import NewTask from "../Presentational/NewTask";
import TasksList from "../Presentational/TasksList";

export default function AppFunction() {
  // hook your code up here ;)

  // set up state variables
  const [newTask, setNewTask] = useState({});
  const [allTasks, setAllTasks] = useState([]);
  
  // define event handlers
  const handleChange = ({ target }) => {
    const { name, value } = target;
    setNewTask((prevState) => {
      ...prevState,
        [name]: value,
        id: Date.now()
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    if (!newTask.title) return;
    setAllTasks((prevState) => [newTask, ...prevState]));
    setNewTask({});
  };

  const handleDelete = (taskIDtoRemove) => {
    setAllTasks((prevState) => prevState.filter(task) => task.id !== taskIDtoRemove));
  };

  // return app JSX code
  return (
      <main>
        <h1>Tasks</h1>
        <NewTask
          newTask={newTask}
          handleChange={handleChange}
          handleSubmit={handleSubmit}
        />
        <TasksList
          allTasks={allTasks}
          handleDelete={handleDelete}
        />
      </main>    
  );
}

// index.js
import React from "react";

import ReactDOM from "react-dom";

// import App from "./Container/AppClass";

import App from "./Container/AppFunction";

ReactDOM.render(

<App />,

document.getElementById("app")

);

Anyone’s help would be deeply appreciated. Thank you!

I spotted three things which need to be corrected.

  • The first mistake is a missing opening parenthesis within your handleChange event handler:
// You wrote:
setNewTask((prevState) => {
// It should be:
setNewTask((prevState) => ({

It has to do with implicit return of an object. See this post for why we need to wrap the curly braces in parentheses (the explanatory text of the “Objects in State” exercise also makes a brief mention of this). Your code does have the closing parenthesis though i.e. the line with })); , so you are only missing the opening parenthesis.

  • The second mistake is an extra closing parenthesis within your handleSubmit event handler:
// You wrote:
setAllTasks((prevState) => [newTask, ...prevState]));
// It should be:
setAllTasks((prevState) => [newTask, ...prevState]);

Here, we are doing an implicit return of an array. Since an array uses brackets [ ] instead of curly braces { }, so we can do an implicit return of the array without the need of parentheses.

  • The third mistake is a missing opening parenthesis within your handleDelete event handler:
// You wrote:
setAllTasks((prevState) => prevState.filter(task) => task.id !== taskIDtoRemove));
// It should be:
setAllTasks((prevState) => prevState.filter((task) => task.id !== taskIDtoRemove));

You are missing an opening parenthesis after filter. You do have the closing parenthesis though, so you only need to insert the opening parenthesis.

Thank you very much!

Agreed, I don’t see the point of taking this course if it offers virtually no guidance on what to do. “Here’s a bunch of code you don’t understand and barely remember, have fun rewriting it”.

3 Likes

This exercice was very tough and I spent moons to debug my code just because of syntax problems…

I used curly braces in my arrow functions inside of the setNewTask function, like that :

newTask => {
({ …newTask, [name]: value, id: Date.now() })
}

Only because of that, my screen became completely blank after typing some text in the input!

Later on, I realized that it has to be in one single line without curly braces as per below:

newTask => ({ …newTask, [name]: value, id: Date.now() })

This kind of syntax error is so hard to debug!
I still cannot figure out why React doesn’t allow me to write arrow functions with curly braces in this context.

In the lesson “Arrays in State”, there is an example with a function called toggleTopping, and inside this function we called setSelected and in this arrow function we used curly braces like that: setSelected((prev) => {
In this example there is a conditional statement so we must use curly braces.

So why in this context we cannot use curly braces ?

Maybe it’s a bit stupid to focus on syntax, but I am frustrated, and I didn’t manage to use React Developers Tool to help me find the error!

It has to do with implicit/explicit returns. If the body of the function has more than one statement, then it is necessary to use curly braces. When the body of the function is just one expression, then we have a choice. The two choices are:

  • Choice A: We can enclose the expression in curly braces. But, if the function is meant to return some value, then we must do an explicit return by using the return keyword. If we omit the return keyword, then the function’s return will be undefined.

  • Choice B: We can choose to omit the curly braces. Whatever the expression evaluates to will be returned implicitly. Trying to return explicitly using the return keyword is not allowed and will cause error to be thrown.

Either we go with Choice A or with Choice B. What we aren’t allowed to do is mix the two approaches. If we go with Choice A (wrap in curly braces) and wish to return something, then we can’t omit the return keyword. If we go with Choice B (omit the curly braces), then we can’t do an explicit return by using the return keyword.

// Explicit Return 
const myFunc1 = (number) => {
    return number + 5;
}

// Implicit Return
const myFunc2 = (number) => number + 5;

// Curly Braces without explicit return will cause undefined return
const myFunc3 = (number) => {
    number + 5;
}

// No Curly Braces and explicit return will cause SyntaxError
const myFunc4 = (number) => return number + 5;

a = myFunc1(10);   // a will be 15
b = myFunc2(10);   // b will be 15
c = myFunc3(10);   // c will be undefined
d = myFunc4(10);   // SyntaxError

There is a twist though. Suppose we want to do an implicit return of an object. We may try to do something like:

/// Curly brace of object mistaken for curly brace of function body

const myFunc = () => { cars: 4, bikes: 7}

a = myFunc();  // SyntaxError

const myFunc = () => { cars: 4 }

a = myFunc();  // undefined

Since Javascript looks at the curly braces in this context as designating the body of a function, so we can’t just use curly braces. We have to wrap them in parentheses so that Javascript knows that this is meant to be an object and not the body of the arrow function. Have a look at this article. It is a short read, but it explains the issue very nicely with examples.

// Implicit Return of an object
const myFunc = () => ({cars: 4, bikes: 7})

a = myFunc();  // a will be {cars: 4, bikes: 7}

We can also do an explicit return, but we must use the return keyword if we want to return some value.

// Explicit Return of an object
const myFunc = () => { 
    return {cars: 4, bikes: 7};
}
a = myFunc();  // a will be { cars: 4, bikes: 7}

In the exercises you mentioned, we are using arrow functions in state setters. State setters expect that some value will be returned to them so that they can replace the previous state with the new state. As long as you respect the syntax of implicit/explicit returns, both approaches can be used.

1 Like

Thank you for the great explanations! It makes it very clear now :smiley:

1 Like
{!newTask.title ? null : (
        <>
          <textarea
            name="description"
            placeholder="Details..."
            value={newTask.description || ""}
            onChange={handleChange}
          />
          <button type="submit">Add Task</button>
        </>
)}

I wonder how this works?
Why here is a empty <> and I know nothing about this syntax.

Revisit the earlier lesson JSX Outer Elements.

…a JSX expression must have exactly one outermost element…

In the snippet you posted, there are two elements textarea and button. Only one outer element is allowed, so we can wrap them in say a <div> ... </div>, but if we don’t want to add extra nodes to the DOM by creating divs, we can instead wrap the elements in a fragment.

Have a look at the documentation:

In the snippet posted by you, the short syntax (mentioned in above link) is used.

Wow, this syntax helps me a lot!
I often wonder if there is a better way instead add <div> when I practice React projects.
I wish I could know <React.Fragment> earlier.

1 Like

Hello,
To better understand what newTask and allTasks represent, I have a question to ask you:

If I understood correctly, newTask is an object that stores, in a consecutive way, all the name and id properties of all the tasks, is it really that?
Is it possible to represent it like this:
{ [name] : valueTask1 ,
id:idTAsk1,
[name] : valueTask2,
id:idTAsk2,
[name] : valueTask3,
id:idTAsk3,
[name] : valueTask4,
id:idTAsk4, etc …}
Is this correct?

And, if I still understand correctly, allTasks represents an array that contains objects that represent all tasks.
Can we imagine it like that?
[{task1},{task2},{task3}, etc…] and looking at it in more detail would that be it? :

[{[name]: valueTask1, id:idTAsk1},{[name]: valueTask2, id:idTAsk2}, {[name]: valueTask3, id:idTAsk3},{[name]: valueTask4, id:idTAsk4,} etc …]

Thanks in advance for your answers

Translated with DeepL Translate: The world's most accurate translator (free version)

newTask is an object and allTasks is an array.

The form displayed on screen consists of an input element for the title of the task, a button for submitting the task and (once we type in a title), a textarea element for entering Details of the task also appears.

newTask starts off being an empty object and initially allTasks is an empty array.

// Initially
newTask ---> {}
allTasks ---> []

As we type in text for the title or for the details, the properties and associated values of the new task are created or updated (depending on how the user is interacting with the form). Once the task is submitted, this new task object is added to the allTasks array. The newTask object is then reset to an empty object.

If you look at the file NewTask.js (you can access it by clicking on the Folder Icon in the top left corner of the editor and then navigate to the Presentational folder), you will see that the HTML input element has been given the attribute name="title" and the textarea element has been given the attribute name="description"

In the setters, we are using spread syntax (to preserve existing properties) and computed property names (see documentation: Object initializer - JavaScript | MDN ) to provide the appropriate properties,

//EXAMPLE - Computed Property Names
let name = "title";

// This in not what we want
let x = {name: "Some text"};
console.log(x); // {name: "Some text"}

// This is what we want
let y = {[name]: "Some text"};
console.log(y); // {title: "Some text"}

Suppose we type in the text "First Task" in the title input box. The event handler handleChange will be triggered and result in

// xxxxx is time in milliseconds when event handler was triggered
newTask ---> { title: "First Task", id: xxxxx }
allTasks ---> []

Suppose we type in text "Complete this task soon" in the Details textarea, then handleChange will be triggered and result in

// yyyyy is time in ms when event handler was triggered
// The spread syntax ... in the setter allows the previous title property to be retained
newTask ---> { title: "First Task", description: "Complete this task soon" , id: yyyyy }
allTasks ---> []

When the "Add Task" button is clicked, the handleSubmit event handler does the following:

newTask ---> {}
allTasks ---> [{ title: "First Task", description: "Complete this task soon" , id: yyyyy}]

If another new task is entered in the form, then:

// While entering task in form
newTask ---> { title: "Second Task", description: "Not so important" , id: zzzzz}
allTasks ---> [{ title: "First Task", description: "Complete this task soon" , id: yyyyy}]

// After submitting
newTask ---> {}
allTasks ---> [ { title: "Second Task", description: "Not so important" , id: zzzzz}, 
              { title: "First Task", description: "Complete this task soon" , id: yyyyy} ]
1 Like

Literally man. It demotivates me so much when I get through a bunch of lessons and then am thrown so far into the deepn end that I have absolutely no clue what is going on. :frowning_face:

agreed guys… I’m at least happy that you guys feel the same as me. I was just looking at my screen like how the ■■■■ am I meant to be able to do this all of a sudden? it’s super demotivating when they instruct stuff as if you should know what it means by now and you literally have no clue what is going on

Hello,
Why is better to copy an entire object with the spread operator than modify the object itself?
Couldn’t lead to performance issues?