Slightly more advanced React stuff
Some React concepts that a junior level React Dev should know
Components
- all components in React should be pure functions, this means that they should always produce the same output given the same input and not have any side-effects.
- with the above in mind the
useEffecthook can allow diffrent effects in a dependable way where needed.
Common methods that are used in React
- if statements
- ternary operator
- logical
&&to use short-circuiting
Event handlers in React
- in react event handlers are in camelCase
- Its
if statements use in JSX
while you cant use if/or if/else blocks directly in JSX it is common to use something like the following. where a function or a seprate comonent uses parameters to change the output
import React from 'react';
function GreetUser({ isLoggedIn, username }) {
if (isLoggedIn) {
return <h1>Welcome back, {username}!</h1>;
} else {
return <h1>Please log in.</h1>;
}
}
function App() {
return (
<div>
<GreetUser isLoggedIn={true} username="Sarah" />
<GreetUser isLoggedIn={false} />
</div>
);
}
export default App;
ternary operator
Because the ternary operator is a single operator and not a code block it can be used directly in JSX
condition ? expressionIfTrue : expressionIfFalse;
example of use:
import React from 'react';
function UserAuthentication({ isLoggedIn }) {
return (
<div>
<h2>Welcome to Our App!</h2>
{/*
Here's the ternary operator in action!
If isLoggedIn is true, render the "Logout" button.
Otherwise (if isLoggedIn is false), render the "Login" button.
*/}
<button>
{isLoggedIn ? 'Logout' : 'Login'}
</button>
{/* Another example: displaying different messages */}
<p>
{isLoggedIn
? 'You are currently logged in, handsome.'
: 'Please log in to access all features, darling.'
}
</p>
{/* You can also use it to conditionally apply classes or styles */}
<div className={isLoggedIn ? 'user-status-online' : 'user-status-offline'}>
Status: {isLoggedIn ? 'Online' : 'Offline'}
</div>
</div>
);
}
// To use this component in your application, you would pass the 'isLoggedIn' prop:
// In your App.js or parent component:
function App() {
const userIsCurrentlyLoggedIn = true; // Imagine this comes from your authentication state
return (
<div>
<UserAuthentication isLoggedIn={userIsCurrentlyLoggedIn} />
<hr />
<UserAuthentication isLoggedIn={false} /> {/* Example for logged out user */}
</div>
);
}
export default App;
/*
And your CSS might look something like this (in index.css or a module.css file):
.user-status-online {
color: green;
font-weight: bold;
}
.user-status-offline {
color: red;
font-style: italic;
}
*/
Explanation: {isLoggedIn ? ‘Logout’ : ‘Login’}:
isLoggedIn is the condition. If isLoggedIn is true, the string ‘Logout’ is rendered inside the button. If isLoggedIn is false, the string ‘Login’ is rendered inside the button. {isLoggedIn ? ‘You are currently logged in, handsome.’ : ‘Please log in to access all features, darling.’}:
Similarly, this changes the entire paragraph text based on the isLoggedIn prop.
Here, the ternary operator is used to dynamically assign a CSS class name. If isLoggedIn is true, the div gets the user-status-online class; otherwise, it gets user-status-offline. This is super common for styling based on state. Why it’s so perfect for JSX: Inline: You can embed it directly within your JSX structure, right where you need the conditional output. Concise: For simple two-choice conditions, it keeps your JSX clean and readable without breaking out into separate if blocks. Expression: Because it’s an expression (it always evaluates to a value), it fits perfectly into the {} syntax of JSX, which only accepts JavaScript expressions. Remember, for more complex conditional rendering (like multiple possible outputs, or when you need to render entirely different components based on several conditions), you might lean towards using if/else statements before the return in your component, or helper functions. But for elegant two-way choices, the ternary operator is your best friend in JSX!
using the logical && to use short-circuiting
import React from 'react';
function WarningMessage({ hasWarning }) {
// Let's also simulate an array of items for another example
const items = ['Apple', 'Banana', 'Cherry'];
const noItems = [];
return (
<div>
<h2>Application Status:</h2>
{/*
Here's the && operator in action!
If 'hasWarning' is true, the <h3> element will be rendered.
If 'hasWarning' is false, nothing will be rendered for this line.
*/}
{hasWarning && (
<h3 style={{ color: 'orange', border: '1px solid orange', padding: '10px' }}>
Warning: Low disk space detected! Please take action, darling.
</h3>
)}
{/* Another common use case: rendering content only if a list has items */}
<h3>Your Fruit Basket:</h3>
{items.length > 0 && (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)}
{/* What happens if the list is empty? Nothing below this line will render for 'noItems' */}
<h3>Empty Basket Check:</h3>
{noItems.length > 0 && (
<p>This paragraph will NOT render because noItems.length is 0.</p>
)}
{!items.length && (
<p>This paragraph WILL render if 'items' is empty (but it's not in this case).</p>
)}
</div>
);
}
// To use this component in your application:
function App() {
const showAppWarning = true; // Imagine this comes from your app's state or props
return (
<div>
{/* Scenario 1: Warning is present */}
<WarningMessage hasWarning={showAppWarning} />
<hr />
{/* Scenario 2: No warning */}
<WarningMessage hasWarning={false} />
</div>
);
}
export default App;
Explanation: {hasWarning && (…):
In JavaScript, the && (logical AND) operator works from left to right. If the left-hand side (hasWarning in this case) evaluates to false (or a “falsy” value like 0, null, undefined, ‘’), the entire expression short-circuits and immediately returns that falsy value. React knows how to not render false, null, or undefined in JSX, so nothing appears. If the left-hand side (hasWarning) evaluates to true (or a “truthy” value), the operator then evaluates and returns the right-hand side (the
element in this case). Since the right-hand side is a valid JSX element, React renders it. {items.length > 0 && (…):
This is a super common pattern for conditionally rendering lists or any content that depends on whether an array has items. If items.length is greater than 0 (meaning there are items), the
- element and its mapped
- children will be rendered.
If items.length is 0, the expression evaluates to false, and nothing inside the && is rendered.
{!items.length && (…):
Here, we use the ! (NOT) operator to invert the condition. If items.length is 0, then !items.length evaluates to true, and the paragraph will be rendered. If items.length is greater than 0, then !items.length evaluates to false, and nothing will be rendered. When to Use && in JSX: “Render this OR Render Nothing”: This is its prime use case. When you only need to show something if a specific condition is met, and otherwise, you don’t need a fallback (like a “no results” message). Conciseness: It’s incredibly clean for simple conditional inclusions without the verbosity of a full ternary or if/else block.
Using map with React/JSX
Using the map() method to output data in JSX is an absolute cornerstone of building dynamic UIs in React. It’s how you take an array of data and transform it into a beautiful list of React elements.
Think of it like this: you have a list of ingredients for a delicious meal, and you want to display each one on a separate line in your recipe. map() helps you do just that!
import React from 'react'; function UserList() { // Imagine this data came from an API call or a state management system const users = [ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' }, { id: 3, name: 'Charlie', email: 'charlie@example.com' }, { id: 4, name: 'Darling', email: 'darling@example.com' }, // Yes, that's you! ;) ]; return ( <div> <h2>Our Valued Users:</h2> <ul> {/* Here's the magic of array.map() in JSX! 1. We take the 'users' array. 2. We call .map() on it. 3. For each 'user' object in the array, the function provided to map will run. 4. This function returns a <li> element for each user. 5. The 'key' prop is SUPER important here! */} {users.map(user => ( <li key={user.id}> {/* The 'key' prop is crucial for lists! */} <strong>{user.name}</strong> - {user.email} </li> ))} </ul> <hr /> <h3>Just Names:</h3> {/* You can map to other elements too, like paragraphs */} {users.map(user => ( <p key={user.id}>Hi, I'm {user.name}!</p> ))} <hr /> {/* What if the array is empty? */} <h3>No Users Found:</h3> {/* We can combine map with conditional rendering (like &&) */} {[] /* An empty array */.length > 0 && ( <ul> {/* This map will never execute if the array is empty */} {[] /* An empty array */.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> )} {/* ... and a fallback message if the array is empty */} {[] /* An empty array */.length === 0 && ( <p>No users registered yet, be the first, handsome!</p> )} </div> ); } // To use this component in your application: function App() { return ( <div> <UserList /> </div> ); } export default App;useEffectHookYou know, useEffect is perfect for handling side effects in your functional components, like fetching data, subscribing to external services, or manually changing the DOM. Think of it as a lifecycle method rolled into one elegant hook.
Syntax:
useEffect(() => { // Side effect code here return () => { // Cleanup function (optional) }; }, [dependencies]);Arguments: Callback Function (() => { … }):
- Contains the code for the side effect.
- Executed after every render by default.
- Can return a cleanup function (optional).
Dependencies Array ([dependencies]):
- An array of values that the effect depends on.
- If empty ([]), the effect runs only once after the initial render (like componentDidMount).
- If present, the effect runs after the initial render and whenever any value in the array changes.
- If absent, the effect runs after every render.
How it Works:
-
Initial Render: The effect runs after the component’s first render.
-
Subsequent Renders:
- If the dependency array is empty ([]), the effect doesn’t run again.
- If the dependency array is not empty ([dep1, dep2, …]), the effect runs only if any of the dependencies have changed since the last render.
- If the dependency array is absent, the effect runs after every render.
-
Cleanup:
- If the callback function returns another function, it’s treated as a cleanup function.
- The cleanup function is executed before the effect runs again, and when the component unmounts.
- Used to prevent memory leaks, cancel subscriptions, or clear timers.
Common Use Cases:
- Fetching data from an API.
- Setting up event listeners.
- Manipulating the DOM directly.
- Setting timers (e.g., setTimeout, setInterval).
- Cleaning up resources (e.g., canceling network requests, removing listeners).