Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally execute useContext in React

I am looking to conditionally call useContext. This is my original code, which runs correctly, but fails tslint.

Component that calls useResourceScope - say Component1

import { useEffect } from 'react';

export function useSubscribeListItemStore(
  inputResources?: ResourceScope
) {
  const resources = inputResources || useResourceScope();
  const listItemStore = resources.consume(listItemStoreKey);
  
  useEffect(function subscribeListItemStore() {
    // do some logic
  }, []);
}

Component that defines useResourceScope - say Component2

import { createContext } from 'preact';
import { useContext } from 'preact/hooks';

export const ResourceScopeContext = createContext<ResourceScope | undefined>(undefined);

export function useResourceScope(): ResourceScope {
  const resources = useContext(ResourceScopeContext);
  if (!resources) {
    throw new Error(
      'error message'
    );
  }
  return resources;
}

This gives me a tslint error: (react-hooks-nesting) A hook cannot be used in a conditional expression

This is my attempt at solving this, but does not work. It does not run correctly and fails at the useContext line in Component2 My thought was that since useContext must be called to fix the tslint errors, I decided to conditionally call the useContext with different created contexts. If the variable inputResources is passed in, it calls useContext with a placeholder context called PlaceHolderContext, which it ignores and returns inputResources. If not, it does useContext using the intended ResourceScopeContext value.

Component that calls useResourceScope - say Component1

import { useEffect } from 'react';

export function useSubscribeListItemStore(
  inputResources?: ResourceScope
) {
  const resources = useResourceScope(inputResources);
  const listItemStore = resources.consume(listItemStoreKey);
  
  useEffect(function subscribeListItemStore() {
    // do some logic
  }, []);
}

Component that defines useResourceScope - say Component2

import { createContext } from 'preact';
import { useContext } from 'preact/hooks';

export const ResourceScopeContext = createContext<ResourceScope | undefined>(undefined);

export function useResourceScope(inputResources?: ResourceScope): ResourceScope {
  const PlaceHolderContext = createContext({ foo: 'bar' });
  const createdContext = inputResources ? PlaceHolderContext : ResourceScopeContext;

  const resources = useContext(createdContext as any);

  if (inputResources) {
    return inputResources;
  }

  if (!resources) {
    throw new Error(
      'error message'
    );
  }
  return resources as any;
}

Could you suggest how I can resolve tslint error here without breaking it?

like image 875
LearnToImprove Avatar asked Aug 12 '26 12:08

LearnToImprove


2 Answers

Rather than conditionally calling the hook, can you conditionally use its return value?

import { useEffect } from 'react';

export function useSubscribeListItemStore(
  inputResources?: ResourceScope
) {
  const contextResources = useResourceScope();
  const resources = inputResources || contextResources;

  const listItemStore = resources.consume(listItemStoreKey);
  
  useEffect(function subscribeListItemStore() {
    // do some logic
  }, []);
}
like image 197
Nick Avatar answered Aug 14 '26 09:08

Nick


First off, https://reactjs.org/docs/hooks-rules.html read the bold text:

Only Call Hooks at the Top Level

Don’t call Hooks inside loops, conditions, or nested functions.

like image 26
Kevin C. Ferron Avatar answered Aug 14 '26 10:08

Kevin C. Ferron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!