This error occurs when trying to access the "length" property of an undefined value, typically on arrays or strings. In React, this commonly happens when component state, props, or API response data are undefined or not properly initialized, leading to crashes when accessing array methods or string properties.
This JavaScript TypeError indicates that your code is attempting to read the "length" property from a value that is undefined. The "length" property is commonly used on arrays (to get the number of elements), strings (to get the number of characters), or array-like objects. In React applications, this error typically occurs when: - State or props haven't been initialized before rendering - API data hasn't loaded yet when the component tries to use it - A function returns undefined instead of an array or string - A conditional check is missing before accessing the length property - Array destructuring or optional chaining is not used properly This is one of the most common runtime errors in React applications, especially when dealing with asynchronous data loading or optional data structures. The error prevents your component from rendering and will crash the entire application or error boundary.
Always initialize state with a default value instead of leaving it undefined. Use an empty array [] if expecting an array:
// BAD - state is undefined
const [items, setItems] = useState();
// GOOD - state defaults to empty array
const [items, setItems] = useState([]);
// For objects
const [data, setData] = useState(null); // or {}
// In class components
constructor(props) {
super(props);
this.state = {
items: [], // NOT undefined
loading: true,
error: null
};
}This ensures that when your component first renders, items.length won't fail because items is always an array, even if empty.
Use conditional checks or optional chaining to safely access length:
// BAD - crashes if items is undefined
return <div>{items.length}</div>;
// GOOD - conditional check
return <div>{items ? items.length : 0}</div>;
// GOOD - optional chaining (nullish coalescing)
return <div>{items?.length ?? 0}</div>;
// GOOD - with ternary for rendering
{items && items.length > 0 ? (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
) : (
<p>No items found</p>
)}
// GOOD - array/object safe access
const itemCount = Array.isArray(items) ? items.length : 0;When fetching data from an API, manage loading and error states:
function UserList() {
const [users, setUsers] = useState([]); // Start with empty array
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchUsers()
.then(data => {
setUsers(data || []); // Fallback to empty array if undefined
setLoading(false);
})
.catch(err => {
setError(err);
setUsers([]); // Clear users on error
setLoading(false);
});
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
// Now safe to access users.length
return (
<div>
<p>Total users: {users.length}</p>
{users.map(user => <div key={user.id}>{user.name}</div>)}
</div>
);
}TypeScript helps catch undefined access issues at compile time:
interface User {
id: string;
name: string;
}
// Defines that items must be an array
const [items, setItems] = useState<User[]>([]);
// Function that returns an array
function getUsers(): User[] {
return []; // Must return array, not undefined
}
// Type guards prevent undefined access
function processItems(items: User[] | undefined) {
// Must check before using length
if (!items || items.length === 0) {
return 'No items';
}
return items.map(item => item.name);
}
// Use union types to be explicit
const [data, setData] = useState<string[] | null>(null);
// Optional chaining works smoothly with types
const count = data?.length ?? 0;Validate props passed from parent components:
import PropTypes from 'prop-types';
// Option 1: PropTypes validation
function ItemList({ items }) {
return items.map(item => <div key={item.id}>{item.name}</div>);
}
ItemList.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired
};
ItemList.defaultProps = {
items: [] // Default fallback
};
// Option 2: TypeScript
interface ItemListProps {
items: Array<{ id: string; name: string }>;
}
function ItemList({ items }: ItemListProps) {
return items.map(item => <div key={item.id}>{item.name}</div>);
}
// Usage - parent must provide items
<ItemList items={[]} /> // Always pass an arrayModern JavaScript provides safe property access patterns:
// Optional chaining (?.) - safely access properties
const length = user?.profile?.hobbies?.length; // Returns undefined if any step is null/undefined
const first = items?.[0]; // Safe array access
const count = callback?.(); // Safe function call
// Nullish coalescing (??) - provide default for undefined/null
const itemCount = items?.length ?? 0; // Use 0 if undefined
const name = user?.name ?? 'Unknown';
const data = response?.data ?? []; // Default to empty array
// Combining them
function renderItems(items) {
const count = items?.length ?? 0;
const maxItems = items?.slice(0, 10) ?? [];
return (
<div>
<p>Showing {count} items</p>
{maxItems.map(item => <div key={item?.id}>{item?.name}</div>)}
</div>
);
}Make sure functions return arrays or strings, not undefined:
// BAD - might return undefined
function getFilteredItems(items) {
if (items.length === 0) {
return; // Returns undefined!
}
return items.filter(item => item.active);
}
// GOOD - always returns array
function getFilteredItems(items) {
if (!Array.isArray(items)) {
return []; // Return empty array
}
return items.filter(item => item.active);
}
// GOOD - explicit return type
function getFilteredItems(items: Item[]): Item[] {
return items.filter(item => item.active);
}
// GOOD - with descriptive defaults
function getItemNames(items: any): string[] {
const validItems = Array.isArray(items) ? items : [];
return validItems.map(item => item?.name ?? 'Unknown').filter(Boolean);
}Create utility functions for safe array operations:
// Utility function for safe length check
const getLength = (value) => {
return Array.isArray(value) || typeof value === 'string'
? value.length
: 0;
};
// Safe map function
const safeMap = (items, callback) => {
return Array.isArray(items) ? items.map(callback) : [];
};
// Safe filter
const safeFilter = (items, predicate) => {
return Array.isArray(items) ? items.filter(predicate) : [];
};
// Usage in components
function Component({ items }) {
return (
<div>
<p>Count: {getLength(items)}</p>
{safeMap(items, item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
// Or use lodash/underscore
import { isEmpty, size } from 'lodash';
function Component({ items }) {
if (isEmpty(items)) return <p>No items</p>;
return <div>Count: {size(items)}</div>;
}Optional Chaining Evolution: Optional chaining (?.) was added to JavaScript in 2020 and is now widely supported. It's the modern way to safely access nested properties without defensive checks at every level. If you need to support older browsers, use a transpiler like Babel.
Nullish vs Falsy Coalescing: The nullish coalescing operator (??) only treats null and undefined as missing values. The OR operator (||) treats all falsy values (0, '', false) as missing, which can cause bugs. Always prefer ?? when providing defaults.
Array Destructuring Safety: When destructuring, use rest elements to catch undefined: const [first = 'default', ...rest] = items ?? []; This ensures safe defaults even if items is undefined.
React.lazy and Suspense: If using code splitting with React.lazy, ensure fallback UI handles undefined component data until Suspense resolves. The component prop can be undefined during loading.
Type Inference in TypeScript: Let TypeScript infer array types from initialization. If you initialize state as useState([]), TypeScript knows it's an array and warns about accessing properties on undefined without checking first.
Runtime Validation Libraries: Consider using libraries like Zod or io-ts for runtime validation of API responses. They catch undefined values before your component tries to access .length, with helpful error messages.
Error Boundaries: Wrap risky components in error boundaries to gracefully handle "cannot read length" errors: <ErrorBoundary fallback={<ErrorUI />}><Component /></ErrorBoundary>. This prevents white screens.
Console Warnings in Development: React's development build will warn about undefined defaultProps and missing PropTypes. Enable these warnings to catch issues early during development.
Testing with Undefined: Write unit tests that explicitly test with undefined values: test('handles undefined items', () => { render(<List items={undefined} />); expect(...).toBe(...); }). This catches these bugs before production.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React