Passing Thoughts: why is props.addThought(thought); provided in AddThoughtForm.js

I’m getting confused with usage of props.

App.js is master, and AddThoughtForm.js is getting called in App.js.

The addThought attribute of prop is defined in App.js, how is it getting called in handleSubmit part of AddThoughtForm.js?

Can you post the code for App.js and AddThoughtForm.js ?

To preserve code formatting in forum posts, see: How do I format code in my posts?

App.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import { AddThoughtForm } from "./AddThoughtForm";
import { Thought } from "./Thought";
import { generateId, getNewExpirationTime } from "./utilities";

export default function App() {
  const [thoughts, setThoughts] = useState([
    {
      id: generateId(),
      text: "This is a place for your passing thoughts.",
      expiresAt: getNewExpirationTime(),
    },
    {
      id: generateId(),
      text: "They'll be removed after 15 seconds.",
      expiresAt: getNewExpirationTime(),
    },
  ]);

  const addThought = (thought) => setThoughts((prev) => [thought, ...prev]);

  const removeThought = (thoughtIdToRemove) => {
    setThoughts((thoughts) =>
      thoughts.filter((thought) => thought.id !== thoughtIdToRemove)
    );
  };

  return (
    <div className="App">
      <header>
        <h1>Passing Thoughts</h1>
      </header>
      <main>
        <AddThoughtForm addThought={addThought} />
        <ul className="thoughts">
          {thoughts.map((thought) => (
            <Thought
              key={thought.id}
              thought={thought}
              removeThought={removeThought}
            />
          ))}
        </ul>
      </main>
    </div>
  );
}

AddThoughtForm.js

import React, { useState } from "react";
import { generateId, getNewExpirationTime } from "./utilities";

export function AddThoughtForm(props) {
  const [text, setText] = useState("");

  const handleTextChanges = (event) => {
    setText(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    if (text.length>0){
    const thought = {
      id: generateId(),
      text: text,
      expiresAt: getNewExpirationTime(),
    };
    props.addThought(thought);
    setText('');
    }
  };

  return (
    <form className="AddThoughtForm"         onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={handleTextChanges}
        aria-label="What's on your mind?"
        placeholder="What's on your mind?"
      />
      <input type="submit" />
    </form>
  );
}

I’m not getting the internals of how prop defination is being modified from parent to children component in addThought attribute of prop

1 Like

In AddThoughtForm.js, we see that the AddThoughtForm component is expecting to receive props. Specifically, in the handleSubmit function, we see the statement:

props.addThought(thought);

The syntax is note-worthy. If we had something like props.someProp or props.text etc., we would expect that we are reading in some provided value (perhaps a string or an object or an array or a boolean or …). But the syntax of the above statement should remind us of a function call. It is reasonable to assume that addThought will be some function and we are going to call this function with an argument of thought. We know what thought is, but we have no idea yet about addThought. All we know is that it is supposed to be a function and it will be passed through the props.

Now, let us shift our attention to App.js. This is where we actually create an instance of the AddThoughtForm component and in doing so also provide the expected props,

<AddThoughtForm addThought={addThought} />

Here addThought is the name of the property, whereas ={addThought} is providing a value for this property. If we look through App.js, we see the arrow function,

const addThought = (thought) => setThoughts((prev) => [thought, ...prev]);

Notice when creating the instance, we used addThought={addThought} instead of addThought={addThought()}. We are NOT making a function call to the addThought function yet. Instead, we are just passing a reference to the function.

Once again, shift attention to the AddThoughtForm component. We have already created an instance of this component. When the form is submitted, the handleSubmit function/event handler is invoked. During the execution of handleSubmit, we execute the statement

props.addThought(thought);

At this point, we know exactly what addThought is thanks to the props.
props.addThought holds a reference to the function we defined in App.js. When we make the above function call, the body of that function is executed.


As an aside, suppose in App.js, we had the exact same code except that we chose a different function name e.g.

// App.js
// ... rest of code same as before ...
const myFunc = (thought) => setThoughts((prev) => [thought, ...prev]);
// ... rest of code same as before ...
<AddThoughtForm addThought={myFunc} />
// ... rest of code same as before ...

then in AddThoughtForm.js, nothing needs to be changed.

// When the following statement is executed
props.addThought(thought);
// props.addThought will actually hold a reference 
// to the myFunc function defined in App.js

Share your thoughts if you still find something confusing.

1 Like

Thanks, this makes props easier to understand

1 Like