Search code examples
javascriptreactjsredux-formrecompose

Using recompose utility as element


I want to use recompose utility functions as react element, so that I can use them in JSX as hoc.

const enhancedInput = props => {
  return (<OnlyUpdateForKeys keys={['name']}>
              <Input
                id="name"
                value={props.name}
                onBlur={props.handleNameBlur}
                onChange={props.updateName}
                type="text"
                className="validate"
                placeholder="Enter Component Name"
              />
            </OnlyUpdateForKeys>)
}

This is what I have tried till now, but it utterly fails.

import { onlyUpdateForKeys } from 'recompose';

export const OnlyUpdateForKeys = ({ keys, children }) => {
  return onlyUpdateForKeys([...keys])(children)(children.props);
};

export default OnlyUpdateForKeys;

because children is a symbol and react-element instance and not a class/function.

react.development.js:368 Uncaught TypeError: Cannot set property 'props' of undefined
at Component (react.development.js:368)
at ShouldUpdate (Recompose.esm.js:558)
at OnlyUpdateForKeys (recomposeComponent.js:4)
at mountIndeterminateComponent (react-dom.development.js:14324)

Can somebody guide me?


Solution

  • onlyUpdateForKeys([...keys]) higher-order component expects React component as an argument, while children is React element:

    onlyUpdateForKeys([...keys])(children)
    

    It would be workable like:

    export const OnlyUpdateForKeys = ({ keys, children }) => {
      const EnhancedChild = onlyUpdateForKeys([...keys])(props => children);
      return <EnhancedChild/>;
    };
    

    But it doesn't make sense because it doesn't prevent child component from being updated. OnlyUpdateForKeys is created on each EnhancedInput render. Input is rendered every time EnhancedInput is rendered too, because children are rendered any way - otherwise they wouldn't be available as props.children.

    While onlyUpdateForKeys is supposed to be used as:

    const EnhancedInput = onlyUpdateForKeys(['name'])(props => (
      <Input ... />
    ))
    

    It's shorter and more efficient than OnlyUpdateForKeys utility component.