React Context API 不适用于自定义 NPM 组件库

IT技术 javascript reactjs react-context
2021-05-24 21:12:48

我已经构建了一个 ReactJS 组件库,用于使用 sim 链接通过 NPM 包安装的多个项目。我想使用上下文 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。

3个回答

也许您正在制作提供上下文的组件的多个实例。假设您有一个 Sound 组件,其开头为:

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

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

有解决的问题是执行一个上下文对象,你可以告诉第二组件的WebPack的供应商,拥有库是一个实现external的,所以当的WebPack达到如“导入声音”行,它不会去进一步和将假设此依赖项在运行时解决。当运行时到来时,它会从主项目获取它的同一个地方获取它。要在 webpack 中执行此操作,例如对于上述“声音”库,请将其添加到您的其他组件(不是主项目):

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

同样在您的组件 package.json 中:

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

你的消费者代码应该是

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

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

当你定义

在此处输入图片说明

你可以像这样使用它

在此处输入图片说明

除了达科的回答,esm并且cjs出口也是一个可能的原因上下文包中的失败。如果您使用钩子 inesm和提供程序 in cjs,您将不会获得该上下文的值。