React Context API 不适用于自定义 NPM 组件库 [英] React Context API not working from custom NPM component library

查看:25
本文介绍了React Context API 不适用于自定义 NPM 组件库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've built a ReactJS component library that I use for multiple projects installed via an NPM package using a sim link. I want to use the context API to pass data from a parent component served from the component library to my base project to be consumed by multiple consumer components also served from the component library. When I try the context is always undefined in my child components.

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

If I place my consumer component in my provider component within my library it works like a champ but this defeats what I'm trying to achieve. If I export both the provider and the consumer to my base project the consumer doesn't see the provider.

这是我的基础项目

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

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

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

This is my provider code exported from my 'component-library'

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>
    );
  }
}

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

This is my content code used in 'component-library'

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

这是我从'component-library'导出的消费者组件

This is my consumer component exported from 'component-library'

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.

Context always comes back undefined as if it doesn't see the parent provider. I think I'm ether doing something wrong initializing the context myself or for some reason the two components I'm importing just don't share the same context. Please help!! Not sure if I should give up on this and just use redux.

推荐答案

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

Maybe you are making multiple instances of the component providing the context. Let's say you have a component Sound, which starts by:

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

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

If you import this library from your main project, the context will be created at the global space. You then use it to render your document tree. But in another component you also imported this library, which had to be resolved during webpack transpilation. It thus has its own copy of the above lines and a context object created in its own space. The problem occurs when you try to use the Consumer, because the Provider was only made by the main project for the first context object, and the second context's provider instance was never instantiated, thus returns undefined.

该问题的解决方案是强制执行单个上下文对象,您可以通过告诉第二个组件的 webpack 提供者拥有的库是一个 external 来实现,因此当 webpack 到达例如进口声音"行,它不会更进一步,并假设此依赖项在运行时已解决.当运行时到来时,它会从主项目获取它的同一个地方获取它.要在 webpack 中执行此操作,例如上面的声音"库,将此添加到您的其他组件(不是主项目):

A solution to the problem is to enforce a single context object, which you can achieve by telling the second component's webpack that the provider-owning library is an external, so when webpack reaches e.g. the "import sound" line, it will not go further and will assume this dependency is resolved at runtime. When runtime comes, it will take it from the same place where the main project is taking it. To do this in webpack, e.g. for above "sound" library, add this to your other component (not main project):

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

也在你的组件 package.json 中:

Also in your component package.json:

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

这篇关于React Context API 不适用于自定义 NPM 组件库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆