Passing Data from Child to Parent with React Hooks
Tags: beginners, react, javascript, hooks
Published: 2020-03-30 06:17:23

I was recently challenged to make a simple working implementation of a react authentication system using hooks. I was linked [this article](https://kentcdodds.com/blog/authentication-in-react-applications) as an example, and found it a pretty interesting way to have a single line controlling the authentication for the entire app. For the demo, I wanted the user to be able to type in a username to 'log in', then have the website display 'hello, [username]' to greet the user.

##The General Layout##

The general idea behind this demo is to have a single state in the root parent component which holds the user authentication. Based on whether or not the user is authenticated, a different version of the website loads.

```javascript
const App = () => {
  const [user, setUser] = useState(null);

  return user ? <AuthWebsite/> : <NoAuthWebsite/>
};
```

simple, right? But how does does the state get updated? There must be a way to pass user information up the component tree so that <NoAuthWebsite/> can update the information stored in the [user] state.

##Passing Data from Child to Parent##

Wait, isn't unidirectional data flow a core design philosophy of react? Well, that is true. And we shouldn't be passing anything up the component tree using the most common method for passing data around, props. However, we can actually design functions in our parent, and pass them _down_ the component tree. It is possible to send variables or any other data back _up_ as an argument that you pass into the function in the child.

A child component passing a username back up the component tree looks like this:
```javascript
const NoAuthWebsite = ({ login }) => {
  const [userName, setUserName] = useState("");

  return (
    <form onSubmit={() => login(userName)}>
      <input
        placeholder="username"
        required="required"
        onChange={e => setUserName(e.target.value)}
        value={userName}
      />
      <button type="submit">
        submit
      </button>
    </form>
  );
};
```
(the state here is just for storing the user response in the form)

So above, login is taken as a prop in the NoAuthWebsite component. When the user loads the website, this component presents the user with a form to fill out a username. This is submitted as an argument to the login function that was passed down as a prop. Now lets add login() as a function in the parent component that we wrote above, and pass it down:
```javascript
const App = () => {
  const [user, setUser] = useState(null);

  return user ? (
    <AuthWebsite logout={() => setUser(null)} user={user} />
  ) : (
    <NoAuthWebsite login={username => setUser(username)} />
  );
};
```

So now we have a username submitted by the user being set in the [user] state. And if that exists, we load the authorized version of the website. And if you noticed, we passed a logout function into our AuthWebsite component so that the user can logout and the website can return to it's default (unauthorized) state. We don't need to pass children up our component tree in this case though, as it just needs to setUser to null. We can build up our authorized website component now, and enable it to welcome the user with their username:
```javascript
const AuthWebsite = ({ logout, user }) => {
  return (
    <div>
      <h2>Hello, {user}</h2>
      <div className="logout_button" onClick={() => logout()}>
        logout
      </div>
    </div>
  );
};
```

And there we have it! A simple webapp authentication demo that passes data from child to parent component via functions!

##Adding to our Application with a More Interesting Example##

The login form that greets our user is a little boring. Lets spice it up while reapplying these same concepts to make a __Modal__, or a pop up overlay card that the user can either submit or click out of. These modal windows are found all over the web and can be used for almost anything.

{% codepen https://codepen.io/PnkFluffyUnicorn/pen/RwPvKKG default-tab=result %}

Achieving this effect can be done fairly simply, by using a ternary to toggle CSS. With CSS, you can control weather an html element appears using the 'display' property. Similarly to what was done in the first example, a binary state can control the className of the component. Then, a function that toggles the state can be passed into the overlay component itself.

```javascript
const NoAuthWebsite = () => {
  const [overlay, setOverlay] = useState(false);

  return (
    <div className="flex_column">
      <div className={overlay ? "overlay_shown" : "overlay_hidden"}>
        <LoginOverlay
          removeOverlay={() => setOverlay(false)}
        />
      </div>
      <h2>You are not Authorized</h2>
      <div className="login_button" onClick={() => setOverlay(true)}>
        Login
      </div>
    </div>
  )
}
```
```CSS
.overlay_shown {
  opacity: 1;
}

.overlay_hidden {
  display: none;
  opacity: 0;
}
```

stopPropagation() is used to stop the onClick function on the overlay_background div from propagating to all its children. Without it, clicking anywhere on the modal would cause the onClick to trigger, and remove the modal.

```javascript
const stopProp = e => {
  e.stopPropagation()
}

const LoginOverlay = ({ removeOverlay }) => {
  const [userName, setUserName] = useState("")

  return (
    <div className="overlay_background" onClick={e => removeOverlay()}>
      <div className="overlay_card" onClick={()) => stopProp(e)}>
        <form onSubmit={e => removeOverlay()}>
          <input
            placeholder="username"
            required="required"
            onChange={e => setUserName(e.target.value)}
            value={userName}
          />
          <button className="form_submit" type="submit">
            submit
          </button>
        </form>
      </div>
    </div>
  )
}
```

And that's it! After connecting those together and adding a little visual display to see the data flow path, you can see the [complete live demo here](https://pnkfluffy.github.io/react_auth_demo/), or the [source code here](https://github.com/pnkfluffy/react_auth_demo).

##Conclusion##

Using functions is a great way to pass data up component trees. It can be used in many ways, most notably rendering based off of user interactions / inputs made in child components. Using this trick with react hooks helps in writing beautiful, maintainable code, as it is easy to follow the flow of logic through functional components and functions themselves.

If you have any questions, comments, issues, or just wanna chat, feel free to shoot me a message.