Conditional Rendering & Displaying Data
Conditional Rendering & Displaying Data
Conditional rendering is the process of showing or hiding elements on the screen based on a condition. For example, showing a loading message while data is being loaded, or an error message if something goes wrong. It helps control what the user sees at different times.
Displaying data means showing the fetched data on the screen. In this project, the recipe data is taken from the state and shown as a list of recipe cards, so users can easily view the results.
const [search, setSearch] = useState("");
const [recipes, setRecipes] = useState([]);
const [loading, setLoading] = useState(false);
const [hasSearched, setHasSearched] = useState(false);
const [selectedRecipe, setSelectedRecipe] = useState(null);
-----------------
<div className="recipe-container mt-6">
{loading ? (
<>
<div className="flex justify-center items-center">
<div className="loader"></div>
</div>
<p className="text-xl text-gray-600 mt-3">
Fetching delicious recipes.....
</p>
</>
) : !hasSearched ? (
<p className="text-gray-500 text-center text-base sm:text-lg">
Your recipes will be displayed here
</p>
) : recipes.length === 0 ? (
// Error Message Box
<div className="error-msg-container flex flex-col items-center justify-center py-6 px-4 md:px-6 lg:px-10">
<FontAwesomeIcon
icon={faBug}
style={{ color: "rgb(255, 60, 44)" }}
className="text-2xl mb-2"
/>
<p className="text-red-600 text-center text-sm md:text-base">
Recipe not found
</p>
<p className="text-red-600 text-center text-sm md:text-base mt-1">
Please check the name or try searching again.
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 recipe-grid gap-2">
{recipes.map((recipe) => (
<div
key={recipe.id}
className="dish flex flex-col cursor-pointer"
onClick={() => {
setSelectedRecipe(recipe);
}}
>
<div className="img-container">
<img src={recipe.thumbnail_url} alt={recipe.name} />
</div>
<div className="dish-text p-3">
<p className="name text-lg line-clamp-1">{recipe.name}</p>
<p className="text-base mt-2 sm:mt-3">
<span className="prep -ml-0.75">⏱ Prep Time:</span>{" "}
{recipe.total_time_minutes
? recipe.total_time_minutes < 60
? `${recipe.total_time_minutes} mins`
: `${(recipe.total_time_minutes / 60).toFixed(1)} hrs`
: "N/A"}
</p>
</div>
</div>
))}
</div>
)}
</div>Explanation:
A. Conditional Rendering
Conditional rendering here controls what the user sees based on different states.
If loading is true, it shows an animated loader and a message while data is being fetched.
If loading is false and hasSearched is still false, it means the user hasn’t searched yet, so it shows a default message.
If a search has been performed but recipes.length is 0, no data was found, so an error message is displayed.
Finally, if data exists, it shows the recipe grid by mapping over the recipes array. This flow ensures the UI updates correctly at every stage—before search, during loading, when no results are found, and when data is available.
B. Displaying the Fetched Data
Data is displayed by using the map() function on the recipes array. This function loops through each recipe object and creates a card for each item, which is why the UI updates dynamically as data is received.
Each card gets its data from the current recipe object—like recipe.thumbnail_url for the image, recipe.name for the title, and recipe.total_time_minutes for the preparation time.
To display the preparation time, a condition is used: if the time is less than 60, it shows minutes
If it is greater than 60, convert it to hours by dividing by 60 and use toFixed(1) to show it in a clean format (like 1.5 hrs).
If no time is available, it shows "N/A."
This is how the data is dynamically populated and formatted inside each card.










