2

Context I created a Context and exported both Producer and Consumer. I am now wrapping my app level example with Producer. I want to be able to consume ContextConsumer inside a module which is served by a different package.

However, when I try to use ContextConsumer inside such module, it throws out the error, cannot call function of undefined.

Code Structure The below is how I have my code structured.

Context-v1 package

Context.js

import React, { Component, createContext } from 'react';
import PropTypes from 'prop-types';
import ZIndexUtils from './zIndexUtils';

const { node } = PropTypes;
const { Provider, Consumer: IDSContextConsumer } = createContext();

class IDSContextProvider extends Component {
  static propTypes = {
    children: node.isRequired
  };

  state = {
    topZIndex: ZIndexUtils.getTopZIndex(),
    incrementTopZIndex: ZIndexUtils.incrementTopZIndex
  };

  render() {
    return (
      <Provider
        value={{
          topZIndex: this.state.topZIndex,
          incrementTopZIndex: this.state.incrementTopZIndex
        }}
      >
        {this.props.children}
      </Provider>
    );
  }
}

export { IDSContextProvider };

export default IDSContextConsumer;

index.js

import IDSContextConsumer, { IDSContextProvider } from './Context';

export {
  IDSContextProvider,
  IDSContextConsumer
};

Dropdown-v1 package This component makes use of another component called as Menu-v1 which is where I am trying to use Consumer to access the increment function that I am passing down from app level example.

import { IDSContextConsumer } from '@ids/context-v1';
...
...
render() {
  return (
    <IDSContextConsumer>
      {
        (context) => (
          <ZIndex assignZIndex getTopZindex={context.incrementTopZIndex}>
            <MenuList
              className={className}
              autoFocus={autoFocus}
              aria-label={this.props['aria-label']}
              onKeyDown={this.handleKeyDown}
              onBlur={this.handleMenuBlur}
              reference={reference}
              ref={refReactDom}
              style={style}
            >
              {items}
            </MenuList>
          </ZIndex>
        )
      }
    </IDSContextConsumer>
  )
}

App example Finally, I am trying to use this Dropdown module into my app. Which is where I expect to see the incrementer function be passed in via context.

import { IDSContextProvider } from '@ids/context-v1'; import { Dropdown, MenuItem } from '@ids/dropdown';

render() {
    return (
      <div>
        <IDSContextProvider>
          <Modal
            open={this.state.openModalDialog}
            onCloseModalDialog={this.handleModalClosing}
            title="Modal with Dropdown"
          >
            <Dropdown
              onBlur={() => console.log('Dropdown blurrrrr')}
              label="Name"
              value={this.state.value}
              onChange={this.handleDropdownChange}
            >
              <MenuItem value="1">Banana</MenuItem>
              <MenuItem value="2">Apple</MenuItem>
              <MenuItem value="3">Guava</MenuItem>
              <MenuItem value="4">Mango</MenuItem>
            </Dropdown>
          </Modal>
        </IDSContextProvider>
        <button className="divRenderButton" onClick={this.handleModalOpening}>Open Modal</button>
      </div>
    );
  }

Modal component in my example

<Portal>
        <Transition
          enterClassName={`${prefix}--slideIn`}
          transition={open ? transitions.enter : transitions.exit}
          onEntered={onShow}
          onExited={onClose}
          exitClassName={`${prefix}--slideOut`}
          unmountOnExit
        >
          <IDSContextConsumer>
            {
              (context) => (
                <ZIndex
                  assignZIndex={open}
                  underlay
                  getTopZindex={context.incrementTopZIndex}
                >
                  <div
                    className={open ? 'divContainerWithUnderlay' : ''}
                  >
                    {
                      open &&
                      <div>
                        <h1 className="divContent">{title}</h1>
                        {
                          this.props.children ? this.props.children : null
                        }
                        <button className="divRenderButton" onClick={this.closeModalDialog}>Close Modal</button>
                      </div>
                    }
                  </div>
                </ZIndex>
              )
            }
          </IDSContextConsumer>
        </Transition>
      </Portal>

Requesting earnest help on this. I have tried the solutions from this forum before and cannot find any approach where the modules from different packages share the context.

  • *cannot call function of undefined* - please, provide exact error message, I believe you misinterpreted it. Please, provide https://stackoverflow.com/help/mcve , it's required for SO questions. The question contains a lot of irrelevant code that could possibly be skipped. A working demo like Stackblitz or Codesandbox will increase chances to solve the problem. The situation with multiple packages is irrelevant. It doesn't matter how many packages are there, as long as exports and imports are correct. It's the same for local modules. – Estus Flask Nov 21 '18 at 07:49

0 Answers0