NachtBlade31
NachtBlade31

Reputation: 13

Delay in storing the content of an event in array by one click in React

I am new to React. I am working on a piece of code. I am trying to make a ToDoList kind of thing. So i have created 3 different component , one for taking input and one for displaying the entered code along with App.jsx. Here are the code for each.

App.jsx

    import React, { useState } from "react";
    import Header from "./Header";
    import Footer from "./Footer";
    import Note from "./Note";
    import CreateArea from "./CreateArea";

    function App() {
      const [arr, setArr] = useState([]);
      function getData(note) {
        // setArr(previous => [...previous, { title: newTitle, content: newContent }]);
        setArr(previous => {return [...previous, note];});
        console.log(arr);
      }
      return (
        <div>
          <Header />
          <CreateArea reply={getData} />
          {arr.map((arry, index) => (
                <Note
                  key={index}
                  id={index}
                  title={arry.title}
                  content={arry.content} 
                />
              ))} 
          <Footer />
        </div>
      );
    }

    export default App;

CreateArea.jsx



    import React, { useState } from "react";

    function CreateArea(props) {
      const [note, setNote] = useState({
        title: "",
        content: ""
      });

      function handleChange(event) {
        const { name, value } = event.target;

        setNote(prevNote => {
          return {
            ...prevNote,
            [name]: value
          };
        });
      }

      function submitNote(event) {
        // const newTitle = note.title;
        // const newContent = note.content;
        // props.reply(newTitle, newContent);
        props.reply(note);
        setNote({
          title: "",
          content: ""
        });
        event.preventDefault();
      }

      return (
        <div>
          <form>
            <input
              name="title"
              onChange={handleChange}
              value={note.title}
              placeholder="Title"
            />
            <textarea
              name="content"
              onChange={handleChange}
              value={note.content}
              placeholder="Take a note..."
              rows="3"
            />
            <button onClick={submitNote}>Add</button>
          </form>
        </div>
      );
    }

    export default CreateArea;

Note.jsx

    import React from "react";

    function Note(props) {
      return (
        <div className="note">
          <h1>{props.title}</h1>
          <p>{props.content}</p>
          <button>DELETE</button>
        </div>
      );
    }

    export default Note;

Now somehow i am getting the result right and the new post are being added as required but when I do a console.log for the array which stores inside getData() in App.jsx ,I observe there is a delayy of one click before the array is being added.

Sample problem

In the images attached.I have added new post with random data but when i see the console log the array is still empty. When i click the Add button for the second time , only then after second click on adding new post is the data being shown. I can't seem to figure out the reasoning behind it. Am I doing something wrong or missing something ?

Upvotes: 1

Views: 315

Answers (2)

Clocher Zhong
Clocher Zhong

Reputation: 2456

This is delay is because useState mutation is asynchronous, you cannot get updated result in one tick.

try console.log result in useEffect hook like below:

function App() {
    const [arr, setArr] = useState([]);
    function getData(note) {
        // setArr(previous => [...previous, { title: newTitle, content: newContent }]);
        setArr(previous => {
            return [...previous, note];
        });
    }
    useEffect(() => {
        console.log(arr);
    });
    return (
        <div>
            <CreateArea reply={getData} />
            {arr.map((arry, index) => (
                <Note
                    key={index}
                    id={index}
                    title={arry.title}
                    content={arry.content}
                />
            ))}
        </div>
    );
}

more info: hooks-reference.html#useeffect

Upvotes: 2

Akshit Mehra
Akshit Mehra

Reputation: 767

Your setArr() from useState() is an asynchronous function. Hence, the console.log(arr) is called before the state is actually updated.

However, you can log arr in the useEffect() hook which is called on every state change, like this:

useEffect(() => {console.log(arr)})

You can find more information about this hook at https://reactjs.org/docs/hooks-effect.html.

Upvotes: 2

Related Questions