Understanding and using React State
What is State in React?
State: Data that is DYNAMIC in your component. It changes over time as users interact with the application.
To use, we must import a function from React called "useState". It is a React Hook. The setup looks as follows:
import React, {useState} from "react"; function Increment() { const [count, setCount] = useState(0); function incrementer() { setCount(count +1) } return <button onClick={incrementer}>{count}</button> }When called, the useState(0) tells React to set an initial value of 0
The useState will return an array of 2 variables:
count: a reference to the current value of the state
setCount: a setter function so we can update the state
In the above, when the button element is clicked, it invokes the incremetor function, which sets the new state to count +1 after each click.
Whenever a state is updated or changed, the component rerenders.
State works asynchronously, meaning it doesn't update until the other tasks in the function are completed.
When updating state based on the previous state, it is better to use a call-back function as follows:
function incrementer(){
setCount((currentCount)=> currentCount + 1)
}
Rules of Hooks
Only call hooks at the top level.
- You shouldn't be calling them inside loops, conditions, or nested functions.
Only call and use hooks inside react components.
State is only for values that are expected to change during the components life
Using React with Arrays and Objects
React will only update state if a new object/array is passed to setState
Any time we need to update and object or array in state, we need to make a new object and call setState with the new Object
For objects:
function Increment() { const [count, setCount] = useState({x : 0}); function incrementer() { setCount(count.x++) } return <button onClick={incrementer}>{count}</button> } // This one wont work as the object is //being mutated but the reference is to the same object // We need to create a new Object as follows for setState to update //and rerender. Below is the correct way setCount({x : count.x +1})
For Arrays:
To add elements in an array in state, you can use the spread operator to make a copy of the array and then add the new item to the array.
const newFoodArray = [...foods, newFood] setFoods(newFoodArray)To remove elements in an array in state, use the .filter method
- calling .filter will return a new array based on which elements match the criteria in the call-back function.
[1,2,3].filter((number) => number !== 3);
//This will return a new array of just [1,2] as they don't = 3
- To update elements in an Array in State use the .map method, which returns a new array with the same length as the original array with the transformations applied to the elements.
[1,2,3].map((number) => {
if (number === 3){
return number + 100;
}
else {
return number;
}
})
// returns [1,2,103] as a new array
Array Cheat Sheet
To add: use the spread operator [...]
to remove, use .filter method
to update, use .map method
React Information Flow
For information to go down the component tree, parents pass PROPS to their children
For information to go up the component tree, we must invoke call-back functions that were passed from the parents to the children as props. When they are invoked by the children, that information is sent back to the parents.
- Any values can be passed from the child component to the parent as arguments of the call-back function
Sibling components cannot communicate directly. We can only communicate vertically in the component tree.
- If multiple components need to share the same information or state, then the state should live in the parent component.
React Context
Prop-drilling: taking in a prop from a parent component only to pass it down to a child component, without needing to use it in the current component.
Can be burdensome for deeply nested component hierarchies.
Use React Context to solve this problem