Managing state is one of the most confusing parts for new React developers β we often wonder:
βShould this be a state, a prop, or a ref?β
In this post, Iβll break down a simple decision-making process to know when to create state and where to put it β using my own small project called Listo π, a packing list app built with React.
π§ When to Create State
Ask yourself a few questions before creating new state.
1οΈβ£ Do I need to store some data?
- β No: Just use a normal variable.
const total = price * quantity;
- β Yes: Go to the next question.
2οΈβ£ Can this data be computed from existing state or props?
If yes, then donβt store it separately β derive it instead.
Example:
const packedCount = items.filter(item => item.packed).length;
No need to store packedCount in useState; itβs derived from items.
3οΈβ£ Should updating this data re-render the component?
- β No: Use a ref instead (
useRef).
const inputRef = useRef();
Refs store data without triggering a re-render.
- β Yes: Go ahead and create local state.
const [items, setItems] = useState([]);
π¦ Example: My "Listo" App
Hereβs how the logic applies to my packing list app.
import { useState } from "react";
function App() {
const [items, setItems] = useState([]);
function handleAddItem(item) {
setItems((items) => [...items, item]);
}
return (
<div className="app">
<Logo />
<Form onAddItem={handleAddItem} />
<PackingList items={items} />
<Stats />
</div>
);
}
ποΈ Where to Place State
Once you decide you need state, the next question is where to keep it.
1οΈβ£ Is it only used inside one component?
Keep it local.
function Form() {
const [description, setDescription] = useState("");
}
2οΈβ£ Is it needed by a child component?
Keep it in the parent and pass it down via props.
<Form onAddItem={handleAddItem} />
3οΈβ£ Is it needed by multiple siblings?
Then lift the state up to their common parent.
In the Listo app:
- The
Formneeds to add new items. - The
PackingListneeds to display those items.
β
Solution: Keep items state in the App component and share it via props.
4οΈβ£ Is it used everywhere in the app?
If many unrelated components need it, youβre dealing with global state.
Use:
- React Context API
- or a library like Zustand, Redux, or Jotai
π§© The Flowchart (Simplified)
Need to store data?
βββ No β Use const
βββ Yes
βββ Can it be derived from props/state?
β βββ Yes β Derive it
βββ No
βββ Should it re-render component?
β βββ No β useRef
βββ Yes β useState
Where to place state?
βββ Used only by this component β keep local
βββ Used by a child β move to parent
βββ Used by siblings β lift to common parent
βββ Used globally β global state (context / redux)
β¨ Key Takeaways
- Donβt overuse state β derive values when possible.
- Lift state up when multiple components need it.
- Refs are great for mutable values that donβt trigger re-renders.
- Always ask: βWho needs this data?β β the answer tells you where the state should live.
π‘ Bonus: The βListoβ App in Action
Example list item rendering:
<li>
<span>
{item.quantity} {item.unit} β {item.description}
</span>
</li>
Output:
2 kg β Apples
π Final Thoughts
Thinking in React means thinking about data flow.
When you understand who owns the data and who needs it, managing state becomes simple, predictable, and fun.
βIf two components need the same data, lift it up.
If only one needs it, keep it local.
If it doesnβt affect rendering, use a ref.β
βοΈ Written by [Usama]
π» Web Developer sharing my React learning journey
π§Ί Built with React: βListoβ β a simple but powerful packing list app
Top comments (0)