- Spec files
npm-react
Describes: pkg:npm/react@19.1.x
- Description
- React is a JavaScript library for building user interfaces with a declarative, component-based approach.
- Author
- tessl
- Last updated
utilities.md docs/
1# Utilities23Utility functions for working with React elements, children manipulation, and development tools. These utilities provide helpful functions for common React operations.45## Capabilities67### isValidElement89Verifies whether an object is a valid React element.1011```typescript { .api }12/**13* Checks if object is a valid React element14* @param object - Object to test15* @returns True if object is a React element16*/17function isValidElement(object: any): object is React.ReactElement;18```1920**Usage Examples:**2122```typescript23import React, { isValidElement } from "react";2425function SafeRenderer({ content }: { content: unknown }) {26if (isValidElement(content)) {27return <div>{content}</div>;28}2930if (typeof content === "string") {31return <span>{content}</span>;32}3334if (typeof content === "number") {35return <span>{content.toString()}</span>;36}3738return <span>Invalid content</span>;39}4041// Usage examples42const validElement = <p>Hello</p>;43const invalidContent = { foo: "bar" };4445console.log(isValidElement(validElement)); // true46console.log(isValidElement("string")); // false47console.log(isValidElement(123)); // false48console.log(isValidElement(invalidContent)); // false4950function ConditionalRenderer({ items }: { items: unknown[] }) {51return (52<div>53{items.map((item, index) => {54if (isValidElement(item)) {55return <div key={index}>{item}</div>;56}57return <div key={index}>Not a React element</div>;58})}59</div>60);61}62```6364### cloneElement6566Clones and returns a new React element using the original element as the starting point.6768```typescript { .api }69/**70* Clones a React element with new props71* @param element - Element to clone72* @param props - Additional or replacement props73* @param children - New children (replaces existing children)74* @returns Cloned React element75*/76function cloneElement<P>(77element: React.ReactElement<P>,78props?: Partial<P> & React.Attributes,79...children: React.ReactNode[]80): React.ReactElement<P>;81```8283**Usage Examples:**8485```typescript86import React, { cloneElement } from "react";8788function Button({89className = "",90onClick,91children92}: {93className?: string;94onClick?: () => void;95children: React.ReactNode;96}) {97return (98<button className={`btn ${className}`} onClick={onClick}>99{children}100</button>101);102}103104function ButtonGroup({ children }: { children: React.ReactNode }) {105return (106<div className="button-group">107{React.Children.map(children, (child, index) => {108if (isValidElement(child) && child.type === Button) {109// Clone button with additional props110return cloneElement(child, {111className: `${child.props.className || ""} group-item`,112onClick: () => {113console.log(`Button ${index} clicked`);114child.props.onClick?.();115}116});117}118return child;119})}120</div>121);122}123124// Usage125function App() {126return (127<ButtonGroup>128<Button onClick={() => alert("Save clicked")}>Save</Button>129<Button onClick={() => alert("Cancel clicked")}>Cancel</Button>130<Button className="danger">Delete</Button>131</ButtonGroup>132);133}134135// Advanced cloning with children replacement136function WrapperComponent({ children }: { children: React.ReactNode }) {137return (138<div>139{React.Children.map(children, (child) => {140if (isValidElement(child)) {141return cloneElement(142child,143{ className: "wrapped" },144<span>🎁</span>, // Replace children145child.props.children146);147}148return child;149})}150</div>151);152}153```154155### Children Utilities156157Utilities for working with the children prop in React components.158159```typescript { .api }160/**161* Utilities for manipulating children162*/163const Children: {164/**165* Maps over children and returns an array166* @param children - Children to map over167* @param fn - Function to call for each child168* @returns Array of mapped children169*/170map<T, C>(171children: C | readonly C[],172fn: (child: C, index: number) => T173): C extends null | undefined ? C : Array<Exclude<T, boolean | null | undefined>>;174175/**176* Iterates over children177* @param children - Children to iterate over178* @param fn - Function to call for each child179*/180forEach<C>(181children: C | readonly C[],182fn: (child: C, index: number) => void183): void;184185/**186* Counts the number of children187* @param children - Children to count188* @returns Number of children189*/190count(children: any): number;191192/**193* Converts children to an array194* @param children - Children to convert195* @returns Array of children196*/197toArray(children: React.ReactNode | React.ReactNode[]): React.ReactElement[];198199/**200* Returns the only child (throws if more than one)201* @param children - Children (must be exactly one)202* @returns Single child203*/204only<T>(children: T): T extends any[] ? never : T;205};206```207208**Usage Examples:**209210```typescript211import React, { Children } from "react";212213// Children.map example214function List({ children }: { children: React.ReactNode }) {215return (216<ul>217{Children.map(children, (child, index) => (218<li key={index} className="list-item">219{child}220</li>221))}222</ul>223);224}225226// Children.forEach example227function DebugChildren({ children }: { children: React.ReactNode }) {228Children.forEach(children, (child, index) => {229console.log(`Child ${index}:`, child);230});231232return <div>{children}</div>;233}234235// Children.count example236function ChildCounter({ children }: { children: React.ReactNode }) {237const count = Children.count(children);238239return (240<div>241<p>Number of children: {count}</p>242{children}243</div>244);245}246247// Children.toArray example248function ReversedChildren({ children }: { children: React.ReactNode }) {249const childArray = Children.toArray(children);250const reversed = childArray.reverse();251252return <div>{reversed}</div>;253}254255// Children.only example256function SingleChildWrapper({ children }: { children: React.ReactNode }) {257const onlyChild = Children.only(children);258259return (260<div className="wrapper">261<h2>Single Child:</h2>262{onlyChild}263</div>264);265}266267// Usage examples268function App() {269return (270<div>271<List>272<span>Item 1</span>273<span>Item 2</span>274<span>Item 3</span>275</List>276277<ChildCounter>278<p>First child</p>279<p>Second child</p>280</ChildCounter>281282<ReversedChildren>283<div>First</div>284<div>Second</div>285<div>Third</div>286</ReversedChildren>287288<SingleChildWrapper>289<button>Only Button</button>290</SingleChildWrapper>291</div>292);293}294```295296### Development and Testing Utilities297298#### act299300Testing utility for wrapping code that triggers React updates.301302```typescript { .api }303/**304* Wraps code that triggers React updates for testing305* @param callback - Function that triggers React updates306* @returns Promise that resolves when updates are complete307*/308function act<T>(callback: () => T | Promise<T>): Promise<T>;309```310311**Usage Examples:**312313```typescript314import React, { useState } from "react";315import { act } from "react";316import { render, screen } from "@testing-library/react";317318function Counter() {319const [count, setCount] = useState(0);320321return (322<div>323<span data-testid="count">{count}</span>324<button onClick={() => setCount(c => c + 1)}>325Increment326</button>327</div>328);329}330331// Test example (with testing library)332test("counter increments", async () => {333render(<Counter />);334335const button = screen.getByText("Increment");336const countElement = screen.getByTestId("count");337338expect(countElement).toHaveTextContent("0");339340// Wrap state updates in act341await act(async () => {342button.click();343});344345expect(countElement).toHaveTextContent("1");346});347348// Manual testing with act349async function testCounterManually() {350const container = document.createElement("div");351document.body.appendChild(container);352353// Initial render354await act(async () => {355ReactDOM.render(<Counter />, container);356});357358const button = container.querySelector("button");359const span = container.querySelector("span");360361console.log("Initial count:", span?.textContent); // "0"362363// Simulate click364await act(async () => {365button?.click();366});367368console.log("After click:", span?.textContent); // "1"369370// Cleanup371document.body.removeChild(container);372}373```374375#### captureOwnerStack376377Development-only function for capturing the current React component owner stack for debugging.378379```typescript { .api }380/**381* Captures the current React component owner stack for debugging purposes382* @returns Stack trace string or null (only available in development builds)383*/384function captureOwnerStack(): string | null;385```386387**Usage Examples:**388389```typescript390import React, { captureOwnerStack } from "react";391392function DebugButton() {393const handleClick = () => {394// Capture the current component stack for debugging395const stack = captureOwnerStack();396console.log("Component stack:", stack);397};398399return <button onClick={handleClick}>Debug Stack</button>;400}401402function Parent() {403return (404<div>405<h1>Parent Component</h1>406<Child />407</div>408);409}410411function Child() {412return (413<div>414<h2>Child Component</h2>415<DebugButton />416</div>417);418}419420// Custom hook for debugging component hierarchies421function useComponentStack() {422React.useEffect(() => {423if (process.env.NODE_ENV === 'development') {424const stack = captureOwnerStack();425console.log("Component mounted with stack:", stack);426}427}, []);428}429430function TrackedComponent() {431useComponentStack();432return <div>This component tracks its stack</div>;433}434```435436#### Version Information437438```typescript { .api }439/**440* React version string441*/442const version: string;443```444445**Usage Examples:**446447```typescript448import React from "react";449450console.log("React version:", React.version); // "19.1.0"451452function VersionDisplay() {453return (454<div>455<p>Running React {React.version}</p>456</div>457);458}459460// Feature detection based on version461function hasFeature(feature: string): boolean {462const [major, minor] = React.version.split(".").map(Number);463464switch (feature) {465case "concurrent":466return major >= 18;467case "suspense":468return major >= 16 && minor >= 6;469case "hooks":470return major >= 16 && minor >= 8;471default:472return false;473}474}475```476477## Advanced Utility Patterns478479### Dynamic Children Manipulation480481```typescript482import React, { Children, cloneElement, isValidElement } from "react";483484interface TabsProps {485activeTab: string;486children: React.ReactNode;487}488489interface TabProps {490id: string;491label: string;492children: React.ReactNode;493}494495function Tab({ children }: TabProps) {496return <div>{children}</div>;497}498499function Tabs({ activeTab, children }: TabsProps) {500const tabs = Children.toArray(children).filter(501child => isValidElement(child) && child.type === Tab502) as React.ReactElement<TabProps>[];503504return (505<div>506<nav>507{tabs.map(tab => (508<button509key={tab.props.id}510className={activeTab === tab.props.id ? "active" : ""}511>512{tab.props.label}513</button>514))}515</nav>516517<div>518{tabs.map(tab => {519if (tab.props.id === activeTab) {520return cloneElement(tab, { key: tab.props.id });521}522return null;523})}524</div>525</div>526);527}528529// Usage530function App() {531return (532<Tabs activeTab="profile">533<Tab id="home" label="Home">534<h2>Home Content</h2>535</Tab>536<Tab id="profile" label="Profile">537<h2>Profile Content</h2>538</Tab>539<Tab id="settings" label="Settings">540<h2>Settings Content</h2>541</Tab>542</Tabs>543);544}545```546547### Conditional Child Rendering548549```typescript550import React, { Children } from "react";551552interface ConditionalProps {553condition: boolean;554children: React.ReactNode;555fallback?: React.ReactNode;556}557558function Conditional({ condition, children, fallback }: ConditionalProps) {559if (!condition) {560return <>{fallback}</>;561}562563return (564<>565{Children.map(children, (child, index) => {566if (isValidElement(child)) {567return cloneElement(child, {568key: child.key || index,569"data-conditional": true570});571}572return child;573})}574</>575);576}577578function App() {579const [showContent, setShowContent] = React.useState(false);580581return (582<div>583<button onClick={() => setShowContent(!showContent)}>584Toggle Content585</button>586587<Conditional588condition={showContent}589fallback={<p>Content is hidden</p>}590>591<h1>Main Content</h1>592<p>This content is conditionally rendered</p>593</Conditional>594</div>595);596}597```598599## Server-Side Security Functions600601Functions for server-side security and data protection in React Server Components.602603### taintUniqueValue604605Taints a unique value to prevent it from being sent to the client.606607```typescript { .api }608/**609* Taints a unique value for server-side security610* @param message - Error message to show if value is accessed on client611* @param lifetime - Lifetime object for the taint612* @param value - Value to taint613*/614function taintUniqueValue(615message: string,616lifetime: any,617value: any618): void;619```620621**Usage Examples:**622623```typescript624import { taintUniqueValue } from "react";625626// Taint sensitive data on the server627function ServerComponent() {628const apiKey = process.env.SECRET_API_KEY;629630// Prevent API key from being sent to client631taintUniqueValue(632"API key cannot be used on the client",633globalThis,634apiKey635);636637return <div>Server rendered content</div>;638}639```640641### taintObjectReference642643Taints an object reference to prevent it from being sent to the client.644645```typescript { .api }646/**647* Taints an object reference for server-side security648* @param message - Error message to show if object is accessed on client649* @param object - Object to taint650*/651function taintObjectReference(652message: string,653object: any654): void;655```656657**Usage Examples:**658659```typescript660import { taintObjectReference } from "react";661662// Taint server-only objects663function ServerDataProcessor() {664const serverDatabase = getServerDatabase();665666// Prevent database connection from being sent to client667taintObjectReference(668"Database connection cannot be used on the client",669serverDatabase670);671672return <div>Processing server data</div>;673}674```675676## Types677678### Utility-Related Types679680```typescript { .api }681interface ReactChildren {682map<T, C>(683children: C | readonly C[],684fn: (child: C, index: number) => T685): C extends null | undefined ? C : Array<Exclude<T, boolean | null | undefined>>;686687forEach<C>(688children: C | readonly C[],689fn: (child: C, index: number) => void690): void;691692count(children: any): number;693toArray(children: ReactNode | ReactNode[]): ReactElement[];694only<T>(children: T): T extends any[] ? never : T;695}696697type ReactText = string | number;698type ReactChild = ReactElement | ReactText;699type ReactFragment = {} | Iterable<ReactNode>;700type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;701702interface Attributes {703key?: Key | null;704}705706interface ClassAttributes<T> extends Attributes {707ref?: Ref<T>;708}709710type CloneElement = <P>(711element: ReactElement<P>,712props?: Partial<P> & Attributes,713...children: ReactNode[]714) => ReactElement<P>;715```