How to use async/await in React props

A new way for bi-directional communication between react components.

Mudafar El Halabi
Leniolabs_
2 min readMay 26, 2019

--

Given two react components Parent and Child, we want to find a way to communicate from the child to the parent and vice-versa.

Child to parent

This is pretty forward, we could simply pass an event handler/function from the parent to the child and let the child trigger it when needed:

function Child({ onAlert }) {  return (      <div onClick={onAlert} style={{ border: "1px dotted" }}>      Click to alert the parent    </div>  );}function Parent() {  function handleChildAlert() {    alert("From child");  }  return <Child onAlert={handleChildAlert} />;}

Parent to child

Unlike the previous case, this one is a little bit cumbersome, to trigger child event from parent component we can use React Refs as follow:

const Child = forwardRef((props, ref) => {  useImperativeHandle(ref, () => ({    getAlert() {      alert("getAlert from Child");    }  }));  return <h1>Child</h1>;});function Parent() {  const childRef = useRef();  funciton handleClick() {    childRef.current.getAlert()
}
return ( <div> <Child ref={childRef} /> <button onClick={handleClick}>Click to alert child</button> </div> );}

Await Parent prop from Child

Let’s create a very simple TODO app with only two components:

  • Todo: with an input, a button to fetch todo and a div to show it
  • App: to fetch todo by id from jsonplaceholder rest API.

Todo is the child and App is the parent component.

Todo will have its internal state to store:

  • todo : an object with API JSON response.
  • todoId : an integer with input value.

It also will call and await the prop onFetchTodo from the parent, passing todoId as an argument as follow:

function Todo({ onFetchTodo }) { const [todo, setTodo] = useState({}); const [todoId, setTodoId] = useState(1); async function handleFetchTodo() {   const todo = await onFetchTodo(todoId);   if (todo) {     setTodo(todo);   } else {     console.log("Fetch error");     // handle error   } } function handleInputChange(event) {   setTodoId(event.target.value); } return (   <div>    <input value={todoId} onChange={handleInputChange} type="number" />    <button onClick={handleFetchTodo}>Fetch todo</button>    <div className="todo"> {todo.title} </div>   </div> );
}

App will fetch the todo related to the passed todoId :

function App() {
async function handleFetchTodo(todoId) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${todoId}`);
const todo = await response.json(); return todo; } catch (e) { console.log(e); } return null; }return (
<div className="App">
<Todo onFetchTodo={handleFetchTodo} />
</div>
);}

That’s it! A workable example is provided with the following codesandbox:

By using async/await props we can not only achieve a smooth bi-directional component communication, but also we can create a generic react component/library to handle the business logic and let the final user provide her own API and data handling (mapping/reducing).

--

--