Mike Suiter
Mike Suiter

Reputation: 1651

Converting React class with "static get defaultProps()" to functional component

As I make code changes to existing React class components I've been converting them to functional components with hooks. We have come components with defaultProps that have labels that are 18n. The values in the i18n() function are loaded with a REST call so they can't be called when the file loads so we have to do this to load them when the instance is created:

  static get defaultProps() {
    return {
      open: false,
      title: i18n('confirm.title'),
      message: i18n('confirm.message'),
      confirmButtonText: i18n('confirm.confirmBtn'),
      cancelButtonText: i18n('confirm.cancelBtn'),
      callback: noop
    };
  }

Obviously converting this scenario to a functional component and doing this doesn't work because values for i18n() aren't available yet.

Confirm.defaultProps = {
  open: false,
  title: i18n('confirm.title'),
  message: i18n('confirm.message'),
  confirmButtonText: i18n('confirm.confirmBtn'),
  cancelButtonText: i18n('confirm.cancelBtn'),
  callback: noop
};

Any ideas on how to convert these class components to functional where i18n() needs called when the component is created?

Upvotes: 3

Views: 1068

Answers (2)

hiddenuser.2524
hiddenuser.2524

Reputation: 4988

Using default props in functional components will be deprecated (https://github.com/facebook/react/pull/16210). You should see a warning when you use them actually.

You can either try and not use props for properties you need i18n for, or use those values as fallback in case the prop is undefined:

e.g.

<div>{props.title || i18n('confirm.title')}</div>

The alternative for functional components is ES6 default params using destructuring - but I'm not sure that will help in your case.

function MyComponent({title = i18n('confirm.title')}) {
...
}

Is your i18n function asynchronous? I that case I'd say you should replace it with a component which renders the message, because those might not be available even when you render initially (even if in most cases they are).

LE: here is a relevant discussion on this topic: https://github.com/yannickcr/eslint-plugin-react/issues/1009

Upvotes: 3

Jacob
Jacob

Reputation: 78840

This should work:

Object.defineProperty(Confirm, 'defaultProps', { 
  get() {
    return {
      open: false,
      title: i18n('confirm.title'),
      message: i18n('confirm.message'),
      confirmButtonText: i18n('confirm.confirmBtn'),
      cancelButtonText: i18n('confirm.cancelBtn'),
      callback: noop
    }; 
  },
  enumerable: true 
});

This will allow you a getter function for the property like you've got in the class version of the code.

Upvotes: 0

Related Questions