{"id":11854,"library":"react-shallow-equal","title":"React Shallow Equal Utilities","description":"The `react-shallow-equal` package provides specific utility functions for performing efficient shallow equality checks within React and React Native environments. It exposes `propsEqual`, `elementsEqual`, and `stylesEqual` functions, designed primarily to optimize component re-renders through `shouldComponentUpdate` by comparing component properties, React elements, and style objects. The current stable version is 0.1.1. However, the package has not seen updates in approximately 8 years, making its release cadence non-existent. It is a fork of `lelandrichardson/shallow-element-equals` and utilizes concepts from `lelandrichardson/style-equal`. Its key differentiator was its specialized focus on React-specific shallow comparisons, but modern React development largely utilizes `React.PureComponent` and `React.memo` for similar optimizations.","status":"abandoned","version":"0.1.1","language":"javascript","source_language":"en","source_url":"https://github.com/Vlad-Zhukov/react-shallow-equal","tags":["javascript","react","react-native","shallowequal","shallow-equal","shallowCompare","shallow-compare","equals","shouldComponentUpdate"],"install":[{"cmd":"npm install react-shallow-equal","lang":"bash","label":"npm"},{"cmd":"yarn add react-shallow-equal","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-shallow-equal","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Runtime dependency for React component context and element comparisons. Expected as a peer dependency.","package":"react","optional":false}],"imports":[{"note":"Primary utility for comparing component props. While the library might support CJS, ESM import is shown in documentation.","wrong":"const propsEqual = require('react-shallow-equal').propsEqual;","symbol":"propsEqual","correct":"import { propsEqual } from 'react-shallow-equal';"},{"note":"Used for comparing React elements. It is a named export, not a default export.","wrong":"import elementsEqual from 'react-shallow-equal';","symbol":"elementsEqual","correct":"import { elementsEqual } from 'react-shallow-equal';"},{"note":"Specialized utility for comparing style objects, useful in React Native or when inline styles are passed as props.","wrong":"const stylesEqual = require('react-shallow-equal');","symbol":"stylesEqual","correct":"import { stylesEqual } from 'react-shallow-equal';"}],"quickstart":{"code":"import React, { PureComponent } from 'react';\nimport { propsEqual } from 'react-shallow-equal';\n\nclass MyOptimizedComponent extends PureComponent {\n  // In a traditional React component (not PureComponent), you would implement this:\n  // shouldComponentUpdate(nextProps, nextState) {\n  //   // Only re-render if props are NOT shallowly equal or state has changed\n  //   return !propsEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);\n  // }\n\n  render() {\n    // Simulate rendering based on props, e.g., from an API call or parent component\n    const { data, isActive, onAction } = this.props;\n    return (\n      <div>\n        <h2>Item: {data.name}</h2>\n        <p>Status: {isActive ? 'Active' : 'Inactive'}</p>\n        <button onClick={onAction}>Perform Action</button>\n        <p>Last updated: {new Date().toLocaleTimeString()}</p>\n      </div>\n    );\n  }\n}\n\n// Example of usage in a parent component\nfunction App() {\n  const [count, setCount] = React.useState(0);\n  const [itemData, setItemData] = React.useState({ id: 1, name: 'Example Item' });\n\n  const handleAction = React.useCallback(() => {\n    console.log('Action performed!');\n    setCount(prev => prev + 1);\n  }, []);\n\n  // This prop object will be new on every render, but MyOptimizedComponent\n  // would only re-render if data.name or isActive actually changed values\n  // if using propsEqual inside shouldComponentUpdate.\n  // With PureComponent, it handles this automatically with its own shallow comparison.\n  const componentProps = {\n    data: itemData,\n    isActive: count % 2 === 0,\n    onAction: handleAction,\n    extraProp: count // This will cause PureComponent to re-render every time it changes\n  };\n\n  React.useEffect(() => {\n    const interval = setInterval(() => {\n      // This update will cause App to re-render, creating new componentProps\n      // PureComponent will then shallow compare these new props.\n      setCount(c => c + 1);\n    }, 2000);\n    return () => clearInterval(interval);\n  }, []);\n\n  return (\n    <div>\n      <h1>Parent App Render Count: {count}</h1>\n      <MyOptimizedComponent {...componentProps} />\n    </div>\n  );\n}","lang":"javascript","description":"Demonstrates `propsEqual` usage within a React component's `shouldComponentUpdate` to prevent unnecessary re-renders based on shallow property comparison, similar to `PureComponent`."},"warnings":[{"fix":"Migrate to `React.PureComponent` or `React.memo` for component optimization. For custom shallow comparisons, consider implementing a modern `shallowEqual` utility or using `lodash.isequal` with a shallow customizer.","message":"This package is considered abandoned, having not been updated in over 8 years. It is highly recommended to use built-in React features like `React.PureComponent` for class components or `React.memo` with `useCallback`/`useMemo` for functional components, which provide similar and often more optimized shallow comparison behavior.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure that state and props are immutable. When updating nested data, always create new objects/arrays at every level that changes to ensure reference equality checks correctly detect updates. For deep comparisons, a custom deep equality function or a library like `lodash.isequal` is necessary.","message":"Shallow equality checks only compare the values of properties at the first level of an object or array. For nested objects or arrays, it only compares their references, not their contents. If a nested object changes its internal values but maintains the same reference, `propsEqual` (and `PureComponent`/`React.memo`) will not detect a change and prevent re-rendering, potentially leading to stale UI.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For new projects or refactoring, prefer using `React.PureComponent` for class components or wrapping functional components with `React.memo`. These are maintained by the React team and integrate seamlessly with the reconciliation process.","message":"The functionality provided by `react-shallow-equal` has been largely superseded by native React features. `React.PureComponent` (introduced in React 15.3.0) and `React.memo` (introduced in React 16.6.0) offer built-in shallow comparison for `props` and `state` out of the box.","severity":"deprecated","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you are using the correct ES Module import syntax: `import { propsEqual } from 'react-shallow-equal';`. If using CommonJS, verify the package exports named properties correctly or adjust your build system (e.g., Babel/Webpack) to handle ESM imports.","cause":"Attempting to import `propsEqual` using CommonJS `require` syntax on a module that might be primarily ES Module (ESM) or packaged incorrectly for CJS, or the package path is incorrect.","error":"TypeError: Cannot destructure property 'propsEqual' of ... as it is undefined."},{"fix":"Adopt immutable data patterns. When updating state or props that contain nested objects, always create new object references for the parent object(s) up to the root if any nested property changes. For example, use spread syntax (`{...prevObj, nested: {...prevObj.nested, prop: newValue}}`) to create new objects.","cause":"Shallow equality (used by `propsEqual` and `PureComponent`/`React.memo`) only compares references for non-primitive values. If a nested object's contents change but its reference remains the same, the shallow comparison will return true (meaning 'no change'), and the component will not re-render.","error":"Component not re-rendering when nested data changes."}],"ecosystem":"npm"}