【问题标题】:Conditionally execute useContext in React在 React 中有条件地执行 useContext
【发布时间】:2021-06-02 01:50:01
【问题描述】:

我希望有条件地调用 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 的占位符上下文,它会忽略并返回inputResources。如果不是,它会使用预期的ResourceScopeContext 值来处理useContext

调用 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 错误吗?

【问题讨论】:

    标签: reactjs react-hooks preact use-context createcontext


    【解决方案1】:

    不是有条件地调用钩子,可以有条件地使用它的返回值吗?

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

    【讨论】:

    • 感谢您的想法。我试过这样做,但它给了我相同的运行时错误 - Uncaught TypeError: Cannot read property 'context' of undefined when I click a button。错误源自 const resources = useContext(ResourceScopeContext);
    • 组件树的上层是否有上下文提供者?
    • 你是对的,我不知道。但是在不更改上下文提供程序以使其在组件树上可用的情况下,我可以在 const resources = useContext(ResourceScopeContext); 中进行更改吗?以免导致错误?我不会使用这里返回的资源。我可以像我最初的尝试一样传入 inputResources 并让它返回,我只希望它不会导致错误。
    • 嗯,我不太确定你在问什么。 useContext 钩子仅适用于来自其提供者的 React 组件树中较低的组件。
    • 对!我很抱歉不清楚。我在问 - 我可以做 const notGoingToBeUsingThisResource = useContext( 不会导致错误的东西);如果这没有意义,请告诉我,我可以回去研究 useContext。
    【解决方案2】:

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

    仅在顶层调用 Hooks

    不要在循环、条件或嵌套函数中调用 Hook。

    话虽如此,https://aganglada.com/blog/how-to-break-the-rules-with-conditional-hooks

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2020-02-11
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 2018-07-25
      • 1970-01-01
      相关资源
      最近更新 更多