在 React 中有条件地执行 useContext

Conditionally execute useContext in React

我希望有条件地调用 useContext。这是我的原始代码,运行正确,但 tslint 失败。

调用 useResourceScope 的组件 - 比如 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
  }, []);
}

定义 useResourceScope 的组件 - 比如 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;
}

这给了我一个 tslint 错误:(react-hooks-nesting) 条件表达式中不能使用钩子

这是我尝试解决的方法,但没有用。它没有 运行 正确并且在 Component2 中的 useContext 行失败 我的想法是因为 useContext 必须调用 来修复 tslint 错误,我决定有条件地调用具有不同创建上下文的 useContext。如果传入变量 inputResources,它会调用 useContext,并使用名为 PlaceHolderContext 的占位符上下文,它会忽略该上下文,并调用 returns inputResources。如果不是,它会 useContext 使用预期的 ResourceScopeContext 值。

调用 useResourceScope 的组件 - 比如 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
  }, []);
}

定义 useResourceScope 的组件 - 比如 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;
}

你能建议我如何在不破坏它的情况下解决这里的 tslint 错误吗?

首先,https://reactjs.org/docs/hooks-rules.html阅读粗体文字:

Only Call Hooks at the Top Level

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

也就是说,https://aganglada.com/blog/how-to-break-the-rules-with-conditional-hooks

除了有条件地调用钩子,你能有条件地使用它的 return 值吗?

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
  }, []);
}