React Element Selector Query (RESQ)
resq (React Element Selector Query) is a JavaScript library designed to query React components and HTML elements within the React Virtual DOM, emulating the functionality of `querySelector` and `querySelectorAll` for native DOM elements. It provides `resq$` for selecting a single matching component and `resq$$` for selecting multiple matches, supporting advanced features like wildcard selector patterns, asynchronous waiting for React to initialize, and filtering results by component state or props. The library is currently stable at version 1.11.0 and requires React v16 or higher. Its primary use cases include automated testing, debugging, and advanced component introspection in client-side React applications. It offers a programmatic interface to the React component tree, allowing developers to access internal component data like props and state through its `RESQNode` return structure.
Common errors
-
ReferenceError: document is not defined
cause Attempting to use `resq` or its utilities in a Node.js environment without a simulated browser DOM.fixEnsure your code runs in a browser environment. If running tests in Node.js, configure a JSDOM environment (e.g., using `jest-environment-jsdom`) to provide the necessary global objects. -
resq error Error: React was not found on the window object after Xms
cause The `waitToLoadReact` function timed out because the React global object (`window.React`) was not available within the allotted time.fixIncrease the timeout value passed to `waitToLoadReact(timeoutInMs)` to allow more time for React to load, or ensure React is loaded on the `window` object if it's not a global dependency. -
TypeError: Cannot read properties of null (reading 'outerHTML')
cause Attempting to access properties like `node.outerHTML` on a `RESQNode` where `node` is `null`, indicating the component might be a fragment or not associated with a direct DOM element.fixCheck if `RESQNode.node` is `null` or `undefined` before attempting to access its properties. Components like React fragments or certain HOCs might not have a direct DOM node.
Warnings
- gotcha Component name resolution can be inconsistent for higher-order components (HOCs), Styled Components, or Material-UI components. The library relies on `displayName` or function/class names, which might be obfuscated or generic. Using React DevTools is recommended to verify the exact component names for selectors.
- gotcha The `waitToLoadReact` function can throw an error if React is not found on the `window` object within the specified timeout duration. This can lead to unhandled promise rejections if not explicitly caught.
- gotcha resq is designed for client-side React applications running in a browser environment, as it interacts directly with the rendered React Virtual DOM and often the browser's `document` object. It is not intended for use in Node.js server-side rendering (SSR) contexts without a JSDOM-like environment.
Install
-
npm install resq -
yarn add resq -
pnpm add resq
Imports
- resq$
const resq$ = require('resq').resq$import { resq$ } from 'resq' - resq$$
const resq$$ = require('resq').resq$$import { resq$$ } from 'resq' - waitToLoadReact
const waitToLoadReact = require('resq').waitToLoadReactimport { waitToLoadReact } from 'resq'
Quickstart
import { resq$, waitToLoadReact } from 'resq';
import React from 'react';
import ReactDOM from 'react-dom';
// A simple React component for demonstration
const MyComponent = () => (
<div data-testid="my-component">Hello from MyComponent</div>
);
// Another component
const AnotherComponent = () => (
<p>Another one</p>
)
// The main application component
const App = () => (
<div>
<MyComponent />
<AnotherComponent />
</div>
);
// Render the application to the DOM
const rootElement = document.createElement('div');
rootElement.id = 'root';
document.body.appendChild(rootElement);
ReactDOM.render(<App />, rootElement);
async function queryComponents() {
try {
// Wait for React to load, then query for 'MyComponent'
await waitToLoadReact(1000); // Wait up to 1 second
const myComponentNode = resq$('MyComponent');
if (myComponentNode) {
console.log('Found MyComponent:', myComponentNode.name, myComponentNode.node.outerHTML);
console.log('MyComponent props:', myComponentNode.props);
} else {
console.log('MyComponent not found after waiting.');
}
// Query for multiple components using a wildcard
const allMyComponents = resq$$('My*');
console.log('\nFound all My* components (count:', allMyComponents.length, '):');
allMyComponents.forEach(comp => console.log('- ' + comp.name));
} catch (error) {
console.error('An error occurred during resq query:', error);
}
}
queryComponents();