Home / Function/ validateUseMemo() — react Function Reference

validateUseMemo() — react Function Reference

Architecture documentation for the validateUseMemo() function in ValidateUseMemo.ts from the react codebase.

Entity Profile

Dependency Diagram

graph TD
  67b24411_23d5_6f16_8d4e_dbebeb847123["validateUseMemo()"]
  50f9142a_be38_a654_5f39_5cea59a5336d["ValidateUseMemo.ts"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|defined in| 50f9142a_be38_a654_5f39_5cea59a5336d
  b2fc2985_a7ba_9865_c2a3_2a7531f27d44["eachInstructionValueOperand()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| b2fc2985_a7ba_9865_c2a3_2a7531f27d44
  02303def_636f_c5b3_a751_1cf138fcea69["pushDiagnostic()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 02303def_636f_c5b3_a751_1cf138fcea69
  ac13f5c1_be17_dd7a_6bd3_66d91c46aadf["create()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| ac13f5c1_be17_dd7a_6bd3_66d91c46aadf
  1a2b7047_24c8_62d6_b328_5f07307d27ab["withDetails()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 1a2b7047_24c8_62d6_b328_5f07307d27ab
  078e94bc_d3da_1437_368b_2db5a97fcbdb["validateNoContextVariableAssignment()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 078e94bc_d3da_1437_368b_2db5a97fcbdb
  4117cd56_ad20_df31_ff25_2a7a507a699a["hasNonVoidReturn()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 4117cd56_ad20_df31_ff25_2a7a507a699a
  41232a25_deb6_6e83_05a8_ae9f961656f7["eachTerminalOperand()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 41232a25_deb6_6e83_05a8_ae9f961656f7
  531eb985_e192_f9a2_2d7b_5deeb85ba95c["asResult()"]
  67b24411_23d5_6f16_8d4e_dbebeb847123 -->|calls| 531eb985_e192_f9a2_2d7b_5deeb85ba95c
  style 67b24411_23d5_6f16_8d4e_dbebeb847123 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts lines 25–181

export function validateUseMemo(fn: HIRFunction): Result<void, CompilerError> {
  const errors = new CompilerError();
  const voidMemoErrors = new CompilerError();
  const useMemos = new Set<IdentifierId>();
  const react = new Set<IdentifierId>();
  const functions = new Map<IdentifierId, FunctionExpression>();
  const unusedUseMemos = new Map<IdentifierId, SourceLocation>();
  for (const [, block] of fn.body.blocks) {
    for (const {lvalue, value} of block.instructions) {
      if (unusedUseMemos.size !== 0) {
        /**
         * Most of the time useMemo results are referenced immediately. Don't bother
         * scanning instruction operands for useMemos unless there is an as-yet-unused
         * useMemo.
         */
        for (const operand of eachInstructionValueOperand(value)) {
          unusedUseMemos.delete(operand.identifier.id);
        }
      }
      switch (value.kind) {
        case 'LoadGlobal': {
          if (value.binding.name === 'useMemo') {
            useMemos.add(lvalue.identifier.id);
          } else if (value.binding.name === 'React') {
            react.add(lvalue.identifier.id);
          }
          break;
        }
        case 'PropertyLoad': {
          if (react.has(value.object.identifier.id)) {
            if (value.property === 'useMemo') {
              useMemos.add(lvalue.identifier.id);
            }
          }
          break;
        }
        case 'FunctionExpression': {
          functions.set(lvalue.identifier.id, value);
          break;
        }
        case 'MethodCall':
        case 'CallExpression': {
          // Is the function being called useMemo, with at least 1 argument?
          const callee =
            value.kind === 'CallExpression' ? value.callee : value.property;
          const isUseMemo = useMemos.has(callee.identifier.id);
          if (!isUseMemo || value.args.length === 0) {
            continue;
          }

          /*
           * If yes get the first argument and if it refers to a locally defined function
           * expression, validate the function
           */
          const [arg] = value.args;
          if (arg.kind !== 'Identifier') {
            continue;
          }
          const body = functions.get(arg.identifier.id);
          if (body === undefined) {
            continue;
          }

          if (body.loweredFunc.func.params.length > 0) {
            const firstParam = body.loweredFunc.func.params[0];
            const loc =
              firstParam.kind === 'Identifier'
                ? firstParam.loc
                : firstParam.place.loc;
            errors.pushDiagnostic(
              CompilerDiagnostic.create({
                category: ErrorCategory.UseMemo,
                reason: 'useMemo() callbacks may not accept parameters',
                description:
                  'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation',
                suggestions: null,
              }).withDetails({
                kind: 'error',
                loc,
                message: 'Callbacks with parameters are not supported',
              }),

Domain

Subdomains

Frequently Asked Questions

What does validateUseMemo() do?
validateUseMemo() is a function in the react codebase, defined in compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts.
Where is validateUseMemo() defined?
validateUseMemo() is defined in compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts at line 25.
What does validateUseMemo() call?
validateUseMemo() calls 8 function(s): asResult, create, eachInstructionValueOperand, eachTerminalOperand, hasNonVoidReturn, pushDiagnostic, validateNoContextVariableAssignment, withDetails.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free