【问题标题】:React Context API not working from custom NPM component libraryReact Context API 在自定义 NPM 组件库中不起作用
【发布时间】:2020-01-18 11:03:55
【问题描述】:

我已经构建了一个 ReactJS 组件库,用于通过 NPM 包使用 sim 链接安装的多个项目。我想使用上下文 API 将数据从组件库提供的父组件传递到我的基础项目,以供多个消费者组件使用,这些消费者组件也来自组件库。当我尝试时,我的子组件中始终未定义上下文。

如果我将我的消费者组件放在我的库中的我的提供者组件中,它就像一个冠军,但这会破坏我想要实现的目标。如果我将提供者和消费者都导出到我的基础项目,消费者看不到提供者。

这是来自我的基础项目

import { Screen, COD, GenericSocketServer } from 'component-library'

export default class View extends React.PureComponent {
  render() {
    return (
      <Screen className="screen odmb1">
        <GenericSocketServer>
          <COD />
        </GenericSocketServer>
      </Screen>
    )
  }
}

这是我从“组件库”导出的提供程序代码

import React from 'react';
import MyContext from "./context";
import COD from './../cod';

export default class GenericSocketServer extends React.Component {
  render() {
    return (
      <MyContext.Provider value={{ foo: 'bar' }}>
        <COD />
        {this.props.children}
      </MyContext.Provider>
    );
  }
}

这是我在“组件库”中使用的内容代码

import React from 'react'
const MyContext = React.createContext()
export default MyContext

这是我从“组件库”导出的消费者组件

import MyContext from "../GenericSocketServer/context"

class COD extends React.Component {
  render() {
    return (
      <React.Fragment>
        <MyContext.Consumer>
          {(context) => { 
            /*
               context comes back undefined 
               I expect { foo: 'bar' }
            */
            console.log('context :', context)
            return (
              <p>This should work</p>
          )}}
        </MyContext.Consumer>
      </React.Fragment>
    )
  }
}

上下文总是返回未定义,就好像它没有看到父提供者一样。我认为我自己在初始化上下文时做错了什么,或者由于某种原因,我正在导入的两个组件不共享相同的上下文。请帮忙!!不知道我是否应该放弃这个并只使用redux。

【问题讨论】:

  • 你有没有想过这个问题?我有同样的问题。我发布了一个类似(稍微更具体)的问题here。如何在 npm 发布的 react 组件中使用上下文?
  • 从来没有,我放弃并开始传递道具。不过,我希望有一个解决方案。如果可以让它工作,这就是我想要使用上下文 API 的方式。
  • 我最终在我的另一个线程中找到了我的问题的答案。当我有机会时,我将发布我自己问题的答案。在发布到 npm 之前,我正在使用 webpack 构建我的组件。这个问题与我配置 webpack.config 文件和 package.json 文件的方式有关。你在用 webpack 构建你的 npm 包吗?如果是这样,您的配置和包文件是什么样的?
  • @SethLutske 很想看到你的回答,因为我遇到了同样的问题
  • 我为我的问题写了an answer。我的问题与这个不同,但它们看起来很相似。我不确定我的回答是否能指出这里的问题,但也许它可能会有所帮助。

标签: javascript reactjs react-context


【解决方案1】:

也许您正在创建提供上下文的组件的多个实例。假设您有一个组件 Sound,它的开头是:

    const { Provider, Consumer } = React.createContext();

如果您从主项目中导入此库,则上下文将在全局空间中创建。然后,您可以使用它来呈现您的文档树。但是在另一个组件中,您还导入了这个库,这必须在 webpack 转译期间解决。因此,它有自己的上述行的副本和在自己的空间中创建的上下文对象。当您尝试使用 Consumer 时会出现问题,因为 Provider 仅由主项目为第一个 context 对象制作,而第二个 context 的 provider 实例从未实例化,因此返回 undefined。

解决这个问题的方法是强制执行单个上下文对象,你可以通过告诉第二个组件的 webpack 提供者拥有的库是一个external 来实现,所以当 webpack 到达例如“导入声音”行,它不会走得更远,并会假设这种依赖关系在运行时已解决。当运行时到来时,它将从主项目获取它的同一个地方获取它。在 webpack 中执行此操作,例如对于上述“声音”库,将其添加到您的其他组件(不是主项目):

{
   ...
   externals: {
      ...
      'sound': 'sound'
   }
   ...
}

也在你的组件 package.json 中:

{
   ...
   peerDependencies: {
     "sound": "^1.2.3"
   }
}

【讨论】:

    【解决方案2】:

    你的消费者代码应该是

          <React.Fragment>
            <MyContext.Consumer>
              {value => /* render something based on the context value */}
            </MyContext.Consumer>
          </React.Fragment>
    

    如官方反应文档所述:https://zh-hant.reactjs.org/docs/context.html

    当你定义时

    你可以像这样使用它

    【讨论】:

      【解决方案3】:

      除了达科的回答,esmcjs 导出也是包中上下文失败的可能原因。如果您使用esm 中的钩子和cjs 中的提供程序,您将无法获得该上下文的值。

      【讨论】:

        【解决方案4】:

        我最近遇到了一个类似的问题,我试图在我的库组件中使用上下文的值,但在主机应用程序中使用提供程序(从包中导入)。

        我设法通过在汇总中捆绑时将 react 和 react-dom external 和 peerDependencies 设置为解决问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-17
          • 1970-01-01
          • 2019-07-05
          • 2022-10-17
          • 1970-01-01
          • 2021-02-23
          • 1970-01-01
          • 2020-08-22
          相关资源
          最近更新 更多