使用 recompose 映射从上下文中消耗的道具

Use recompose to map props consumed from context

我有一个功能组件需要渲染道具 heightwidth。我们称它为 PureSizableDiv:

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

我还有一个名为 Size:

的 React 上下文
import React from 'react';
import { compose, fromRenderProps } from 'recompose';

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

而不是像这样手动创建一个新的 HoC:

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

我想知道是否有使用 recompose 的更短更简洁的方法来执行此操作。 我试过了

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

但是得到了错误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.

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

出现错误是因为您没有使用 compose 导出组件:

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

我已经连接了我的组件,但我没有正确使用上下文 API。 我修复了代码,它使用 recompose 中的 fromRenderProps 完美运行。 工作代码:

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>