react-smart-effect
Version:
Enhanced React useEffect and useLayoutEffect hooks with smart dependency tracking, debugging tools, and automatic optimization
96 lines (95 loc) • 3.58 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = babelPluginSmartEffect;
exports.createBabelConfig = createBabelConfig;
const core_1 = require("@babel/core");
/**
* Babel plugin to analyze useSmartEffect dependencies
*/
function babelPluginSmartEffect() {
return {
name: 'babel-plugin-react-smart-effect',
visitor: {
CallExpression(path, state) {
const { node } = path;
// Check if this is a useSmartEffect call
if (core_1.types.isIdentifier(node.callee) &&
(node.callee.name === 'useSmartEffect' ||
node.callee.name === 'useDeepEffect' ||
node.callee.name === 'useDebugEffect' ||
node.callee.name === 'useSmartLayoutEffect')) {
analyzeDependencies(path, state);
}
}
}
};
}
function analyzeDependencies(path, state) {
var _a;
const { node } = path;
const { opts = {} } = state;
if (node.arguments.length < 2) {
return; // No dependencies array
}
const depsArg = node.arguments[1];
if (!core_1.types.isArrayExpression(depsArg)) {
return; // Dependencies not an array literal
}
const dependencies = depsArg.elements;
const issues = [];
const fixes = [];
dependencies.forEach((dep, index) => {
if (!dep)
return;
// Check for potentially missing dependencies
if (core_1.types.isObjectExpression(dep) || core_1.types.isArrayExpression(dep)) {
issues.push(`Dependency at index ${index} is an object/array literal that will be recreated on every render`);
if (opts.autoFix) {
// Suggest wrapping with useMemo
fixes.push(() => {
console.log(`Consider wrapping dependency at index ${index} with useMemo`);
});
}
}
// Check for function expressions
if (core_1.types.isFunctionExpression(dep) || core_1.types.isArrowFunctionExpression(dep)) {
issues.push(`Dependency at index ${index} is a function expression that will be recreated on every render`);
if (opts.autoFix) {
fixes.push(() => {
console.log(`Consider wrapping dependency at index ${index} with useCallback`);
});
}
}
// Check for missing dependencies (simplified analysis)
if (core_1.types.isIdentifier(dep)) {
const binding = path.scope.getBinding(dep.name);
if (!binding) {
issues.push(`Dependency '${dep.name}' at index ${index} is not defined in scope`);
}
}
});
// Report issues
if (issues.length > 0) {
const filename = state.filename || 'unknown';
const line = ((_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) || 'unknown';
const message = `[babel-plugin-react-smart-effect] ${filename}:${line}\n${issues.join('\n')}`;
if (opts.warnOnly) {
console.warn(message);
}
else {
throw path.buildCodeFrameError(message);
}
// Apply fixes if enabled
if (opts.autoFix && fixes.length > 0) {
fixes.forEach(fix => fix());
}
}
}
// Export plugin configuration helper
function createBabelConfig(options = {}) {
return {
plugins: [
[babelPluginSmartEffect, options]
]
};
}
;