import { useState } from 'react';
export const Page = () => {
const [search, setSearch] = useState('');
const onSearch = (event) => {
setSearch(event.target.value);
};
return (
<div>
<header>
<input value={search} onChange={onSearch} />
</header>
<Sidebar />
<ProductsList />
</div>
);
};
import { useState } from 'react';
const SearchInput = () => {
const [search, setSearch] = useState('');
const onSearch = (event) => {
setSearch(event.target.value);
};
return <input value={search} onChange={onSearch} />;
};
export const Page = () => {
return (
<div>
<header>
<SearchInput />
</header>
<Sidebar />
<ProductsList />
</div>
);
};
import { useEffect, useState } from 'react';
export const ItemsInfo = ({ items }) => {
const [count, setCount] = useState(items.length);
useEffect(() => {
setCount(items.length);
}, [items]);
return (
<div>
<div>Total: {count}</div>
<ul>
{items.slice(0, 3).map((item) => (
<li key={id}>{title}</li>
))}
</ul>
</div>
);
}; export const ItemsInfo = ({ items }) => {
const count = items.length;
return (
<div>
<div>Total: {count}</div>
<ul>
{items.slice(0, 3).map((item) => (
<li key={id}>{title}</li>
))}
</ul>
</div>
);
}; export const Dashboard = ({ userName }) => {
return (
<div>
<div>{userName}</div>
<div>Notifications</div>
<div>Settings</div>
</div>
);
};
const UserInfo = ({ userName }) => {
return <div>{userName}</div>;
};
const Notifications = () => {
return <div>Notifications</div>;
};
const Settings = () => {
return <div>Settings</div>;
};
export const Dashboard = ({ userName }) => {
return (
<div>
<UserInfo userName={userName} />
<Notifications />
<Settings />
</div>
);
};
const Memoized = React.memo(Component, arePropsEqual);
import { memo, useState } from 'react';
const SaveButton = memo(({ onSave }) => {
return <button onClick={onSave}>Save</button>;
});
export const Page = () => {
const [count, setCount] = useState(0);
const onIncrement = () => {
setCount((prev) => prev + 1);
};
return (
<div>
<SaveButton onSave={() => foo()} />
<button onClick={onIncrement}>{count}</button>
</div>
);
}; import { memo, useState, useCallback } from 'react';
const SaveButton = memo(({ onSave }) => {
return <button onClick={onSave}>Save</button>;
});
export const Page = () => {
const [count, setCount] = useState(0);
const onSave = useCallback(() => {
foo();
}, []);
const onIncrement = () => {
setCount((prev) => prev + 1);
};
return (
<div>
<SaveButton onSave={onSave} />
<button onClick={onIncrement}>{count}</button>
</div>
);
};
import { memo, useCallback, useState } from 'react';
const SaveButton = memo(
({ onSave, disabled }) => {
return (
<button onClick={onSave} disabled={disabled}>
Save
</button>
);
},
(prevProps, nextProps) => {
return prevProps.disabled === nextProps.disabled;
}
);
export const Page = () => {
const [count, setCount] = useState(0);
const [disabled, setDisabled] = useState(false);
const onIncrement = () => {
setCount((prev) => prev + 1);
};
const onToggleDisabled = () => {
setDisabled((prev) => !prev);
};
const onSave = useCallback(() => {
foo();
}, []);
return (
<div>
<SaveButton onSave={onSave} disabled={disabled} />
<button onClick={onIncrement}>{count}</button>
<button onClick={onToggleDisabled}>
Toggle disabled: {String(disabled)}
</button>
</div>
);
};
import { useState } from 'react';
export const Products = ({ items }) => {
const [query, setQuery] = useState('');
const filteredItems = items
.filter((item) => item.toLowerCase().includes(query.toLowerCase()))
.sort((firstItem, secondItem) => firstItem.localeCompare(secondItem));
const handleQueryChange = (event) => {
setQuery(event.target.value);
};
const itemsToDisplay = filteredItems.join(', ');
return (
<>
<input value={query} onChange={handleQueryChange} />
<div>{itemsToDisplay}</div>
</>
);
};
import { useState, useMemo } from 'react';
export const Products = ({ items }) => {
const [query, setQuery] = useState('');
const filteredItems = useMemo(() => {
const normalizedQuery = query.toLowerCase();
return items
.filter((item) => item.toLowerCase().includes(normalizedQuery))
.sort((firstItem, secondItem) => firstItem.localeCompare(secondItem));
}, [items, query]);
const handleQueryChange = (event) => {
setQuery(event.target.value);
};
const itemsToDisplay = filteredItems.join(', ');
return (
<>
<input value={query} onChange={handleQueryChange} />
<div>{itemsToDisplay}</div>
</>
);
};
import { createContext, useContext, useState } from 'react';
const AppContext = createContext(null);
const Header = () => {
const context = useContext(AppContext);
if (!context) {
return null;
}
const textToDisplay = context.state.isLoggedIn ? 'Welcome' : 'Please log in';
return <div>{textToDisplay}</div>;
};
const Content = () => {
const context = useContext(AppContext);
if (!context) {
return null;
}
return <div className={context.state.theme}>Main</div>;
};
export const App = () => {
const [state, setState] = useState({ isLoggedIn: false, theme: 'light' });
return (
<AppContext.Provider value={{ state, setState }}>
<Header />
<Content />
</AppContext.Provider>
);
};
import { createContext, useContext, useState } from 'react';
const AuthContext = createContext(false);
const ThemeContext = createContext('light');
const Header = () => {
const isLoggedIn = useContext(AuthContext);
const textToDisplay = isLoggedIn ? 'Welcome' : 'Please log in';
return <div>{textToDisplay}</div>;
};
const Content = () => {
const theme = useContext(ThemeContext);
return <div className={theme}>Main</div>;
};
export const App = () => {
const [isLoggedIn] = useState(false);
const [theme] = useState('light');
return (
<AuthContext.Provider value={isLoggedIn}>
<ThemeContext.Provider value={theme}>
<Header />
<Content />
</ThemeContext.Provider>
</AuthContext.Provider>
);
};
<AppContext.Provider value={{ isLoggedIn, theme }}>
{children}
</AppContext.Provider> import { useMemo } from 'react';
const contextValue = useMemo(() => {
return { isLoggedIn, theme };
}, [isLoggedIn, theme]);
return (
<AppContext.Provider value={contextValue}>
{children}
</AppContext.Provider>
)
export const TodoList = ({ todos }) => {
return (
<ul>
{todos.map((item, index) => (
<li key={index}>{item.text}</li>
))}
</ul>
);
};
export const TodoList = ({ todos }) => {
return (
<ul>
{todos.map(({ text, id }) => (
<li key={id}>{text}</li>
))}
</ul>
);
};
import { useDeferredValue, useMemo, useState } from 'react';
export const Search = ({ items }) => {
const [searchQuery, setSearchQuery] = useState('');
const deferredSearchQuery = useDeferredValue(searchQuery);
const filteredItems = useMemo(() => {
const normalizedQuery = deferredSearchQuery.toLowerCase();
return items.filter((item) => item.toLowerCase().includes(normalizedQuery));
}, [items, deferredSearchQuery]);
const handleSearchChange = (event) => {
setSearchQuery(event.target.value);
};
const textToDisplay = `Found: ${filteredItems.length}`;
return (
<>
<input value={searchQuery} onChange={handleSearchChange} />
<div>{textToDisplay}</div>
</>
);
};
import { useTransition, useState, useMemo } from 'react';
export const Filters = ({ items }) => {
const [searchQuery, setSearchQuery] = useState('');
const [isPending, startTransition] = useTransition();
const filteredItems = useMemo(() => {
const normalizedQuery = searchQuery.toLowerCase();
return items.filter((item) => item.toLowerCase().includes(normalizedQuery));
}, [items, searchQuery]);
const handleOnClick = () => {
startTransition(() => {
setSearchQuery((previousQuery) => `${previousQuery}a`);
});
};
const textToDisplay = isPending ? 'Updating' : `Items: ${filteredItems.length}`;
return (
<>
<button onClick={handleOnClick}>Add filter</button>
<div>{textToDisplay}</div>
</>
);
};
import { lazy, Suspense, useState } from 'react';
const Settings = lazy(() => import('./Settings'));
export const App = () => {
const [open, setOpen] = useState(false);
return (
<div>
<button onClick={() => setOpen(true)}>Open settings</button>
{open ? (
<Suspense fallback={<div>Loading...</div>}>
<Settings />
</Suspense>
) : null}
</div>
);
}; import { useState, useEffect } from 'react';
export const Users = ({ orgId }) => {
const [users, setUsers] = useState([]);
const options = { headers: { 'x-org': orgId } };
useEffect(() => {
const loadUsers = async () => {
const response = await fetch('/api/users', options);
const data = await response.json();
setUsers(data);
};
loadUsers();
}, [options]);
return <div>{users.length}</div>;
};
import { useState, useEffect } from 'react';
export const Users = ({ orgId }) => {
const [users, setUsers] = useState([]);
useEffect(() => {
const options = { headers: { 'x-org': orgId } };
const loadUsers = async () => {
const response = await fetch('/api/users', options);
const data = await response.json();
setUsers(data);
};
loadUsers();
}, [orgId]);
return <div>{users.length}</div>;
};
import { useState, useEffect } from 'react';
export const SearchUsers = () => {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
useEffect(() => {
const timeoutId = setTimeout(() => {
setDebouncedQuery(query);
}, 300);
return () => clearTimeout(timeoutId);
}, [query]);
const handleChange = (event) => {
setQuery(event.target.value);
};
return (
<>
<input value={query} onChange={handleChange} />
<div>Debounced: {debouncedQuery}</div>
</>
);
}; import { useState, useEffect } from 'react';
export const Users = ({ query }) => {
const [users, setUsers] = useState([]);
useEffect(() => {
const abortController = new AbortController();
const loadUsers = async () => {
try {
const data = await fetchUsers({
query,
signal: abortController.signal,
});
setUsers(data);
} catch (error) {
if (error.name === 'AbortError') {
return;
}
return;
}
};
loadUsers();
return () => abortController.abort();
}, [query]);
return <div>{users.length}</div>;
};