-
Notifications
You must be signed in to change notification settings - Fork 10
Lesson 1.4
React has one-way data flow (i.e. unidirectional data flow) which means data will flow down from the parent component to the child components. There is a saying “React data flows down, and events flow up”.
Unidirectional data flow means that you send data from parent to child with props and you update data from child to parent with events. Other libraries such as Angular or Vue have two-way data flow (bidirectional data flow).
When you update the state, it may not immediately update your stateful variables. Instead, it actually just schedules, or enqueues an update to the component’s state. The reason for this behavior is it reduces the number of unnecessary component re-renders which improves performance.
The asynchronous nature of updating state can be a cause of bugs or unexpected behavior in a React app. The problem occurs that if you try to use the stateful variable immediately after you update it you may not get the most current state value.
If your state change is dependent on the current state, you can alleviate this issue by passing a function to your state setter function, rather than that a value or variable.
setCounter((prevCount) => {return prevCount+1});
When you pass a function to the setter function (setCounter), that function will receive the current state of the stateful variable (prevCount). The function that you pass to the setter function is called an updater function. The updater function is guaranteed to get the latest state value as a parameter.
If your stateful variable contains an object or array, you can replace the value by passing in a new object or array. But, if your new state depends on the old state, you’ll need to make a copy of the existing array or object, modify it, and then pass the copy of the array or object into the setter function.
Having a lot of components that each independently maintains their own state can increase the complexity of your app. To turn stateful components into stateless components, React developers use a technique called “lifting state up”.
This means that, instead of a component controlling its own state, you can have a component at a higher level in the hierarchy store the state. This state can then be passed down as props to the components that need it. This is very commonly done when sibling components need to share the same state as well. Lifting state up gives you the benefit of having fewer components that can cause your user interface to change, it makes your components more easily reusable, and makes your app easier to test.
- Open
/src/App.jsx - Create new state variable named
todoListwith settersetTodoListand default value of an empty Array - Pass
todoListstate as a prop namedtodoListto theTodoListcomponent - Open
/src/TodoList.jsx - Add
propsas a parameter to theTodoListfunctional component - Change
todoListto reference props instead of the hard-coded variable - Delete the hard-coded
todoListvariable - Run your application and view in browser
- Verify that your Todo List is now empty (no list items)
- Open
/src/AddTodoForm.jsx - Create new state variable named
todoTitlewith settersetTodoTitle - Modify the
<input>element to be a controlled input- Add
valueprop equal totodoTitlefrom component props - Add
onChangeprop equal tohandleTitleChangefunction reference (we will declare this function in the next step)
- Add
- Above the
handleAddTodofunction, declare a new function namedhandleTitleChangethat takeseventas a parameter- First, retrieve the input value from the
eventobject and store in variable namednewTodoTitle - Then, call the state setter
setTodoTitleand passnewTodoTitle
- First, retrieve the input value from the
- In the
handleAddTodofunction, remove thetodoTitlevariable and updateonAddTodocallback handler to pass ourtodoTitlestate variable instead - Run your application and view in browser
- Enter a new todo in "Add Todo" form, submit, and verify that the title appears below
- Open
/src/App.jsx - Remove the
newTodostate variable and the corresponding JSX that displays it - Declare a new function named
addTodothat takesnewTodoas a parameter- Call the
setTodoListstate setter and use the spread operator to pass the existing Objects in thetodoListArray along with thenewTodoObject
- Call the
- Change the value of the
onAddTodoprop forAddTodoFormtoaddTodo - Open
/src/AddTodoForm.jsx - Inside
handleAddTodo, update theonAddTodocallback prop to pass an Object instead of a String; Object should have the following properties:-
title: equal totodoTitle -
id: unique identifier (hint: useDate.now()to generate a unique number)- Disclaimer: we are suggesting
Date.now()for now as a placeholder for unique number generation, but in the future you should not use this
- Disclaimer: we are suggesting
-
- Inside
handleAddTodo, remove thereset()method and replace it with logic to reset thetodoTitlestate to an empty String - Run your application and view in browser
- Enter a todo in "Add Todo" form, submit, and verify item is visible in todo list
- Enter another todo, submit, and verify that two items are visible in todo list
- Open
/src/TodoList.jsxand updatepropsto use destructuring - Open
/src/TodoListItem.jsxand updatepropsto use destructuring - Open
/src/AddTodoForm.jsxand updatepropsto use destructuring