2

I have a functional component that required props height and width to be rendered. Let's call it PureSizableDiv:

const PureSizableDiv = ({ height, width }) =>
    <div style={{ height, width }}>I'm a div!</div>

I also have a React context called Size:

import React from 'react';
import { compose, fromRenderProps } from 'recompose';

export const { SizeProvider, SizeConsumer } = React.createContext({
  height: null,
  width: null,
});

Instead of manually creating a new HoC like this:

export const withSize = Component => (props) =>
  <SizeConsumer>
    {
      ({ height, width }) =>
        <Component
          height={height}
          width={width}
          {...props}
        />
    }
  </SizeConsumer>; 

I'd like to know if there's a shorter a cleaner way using recompose to do this. I tried

export const withSize = compose(
  fromRenderProps(SizeConsumer, ({ height, width }) => ({ height, width })),
);

But got the error Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Augusto Franzoia
  • 570
  • 3
  • 13

2 Answers2

4

I had connected my component, but I wasn't using properly the Context API. I fixed the code and it worked flawlessly using fromRenderProps from recompose. Working code:

import React from 'react';
import { compose, fromRenderProps } from 'recompose';

const PureSizableDiv = ({ height, width }) =>
  <div style={{ height, width }}>I am a div!</div>;

const SizeContext = React.createContext({
  height: null,
  width: null,
});

const withSize = compose(
  fromRenderProps(SizeContext.Consumer, ({ height, width }) => ({ height, width })),
);

// Usage
const Wrapper = ({ children, height, width }) => 
  <SizeContext.Provider
    value={{
      height: height,
      width: width,
    }}
  >
    {children}
  </SizeContext.Provider>;

const SizedDiv = withSize(PureSizableDiv);

// Render components
<Wrapper>
  <SizedDiv/>
</Wrapper>
Augusto Franzoia
  • 570
  • 3
  • 13
2

You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

The error is appearing it's because you're not exporting the Component with the compose:

export const withSize = compose(
  fromRenderProps(SizeConsumer, ({ height, width }) => ({ height, width })),
)(Component);
// ^^
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231