How to migrate from defaultProps to Default Parameters

Viewed 42

I have a Loader component which works as expected with defaultProps:

const Loader = ({ inner, outer, ...rest }) => {
  return (
    <svg fill="none" viewBox="0 0 200 152" {...rest}>
      <path
        fill="none"
        id={inner.id}
        stroke={inner.color}
        d="M99.217 100.606L58.302 29.74h81.829l-40.914 70.866z"
      />
      <path
        fill="none"
        id={outer.id}
        stroke={outer.color}
        d="M100 151L13.398 1h173.205L100 151z"
      />
    </svg>
  );
};

Loader.defaultProps = {
  id: 'loader',
  inner: {
    id: 'inner',
    color: 'black'
  },
  outer: {
    id: 'outer',
    color: 'black'
  }
};

ReactDOM.render(<Loader />, document.getElementById('root'));
<div id="root">

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

I want to migrate it to use Default Parameters while spreading a predefined defaultProps, but I can't figure it out:

const defaultProps = {
  id: 'loader',
  inner: {
    id: 'inner',
    color: 'black'
  },
  outer: {
    id: 'outer',
    color: 'black'
  }
};

// Not working, runtime exception - `id is undefined`
const Loader = ({ inner, outer, ...rest } = defaultProps) => {
  return ...
};

// works, but id is still undefined
const Loader = ({
  inner = defaultProps.inner,
  outer = defaultProps.outer,
  ...rest
}) => { return {...}; }

Sandbox with all examples above:

Edit Q-DefaultProps-to-ES6-Defaults

1 Answers

I don't think you can if you want the outermost id to be in rest (because you can't define a default for a rest target). But if you accept the outermost id as a named destructured parameter, you can do this by specifying the default values within the destructuring in the function signature, and assigning a blank default to the parameter as its default:

const Loader = ({
         id = 'loader',       //
         inner = {            //
             id: 'inner',     //
             color: 'black'   //
         },                   // Various defaults for the destructuring
         outer = {            //
           id: 'outer',       //
           color: 'black'     //
         },                   //
         ...rest
    } = {}
//   ^^^^^---- default for the parameter itself
) => {
        // ...
};

(Formatting is a real pain, though. :-) )

Live Example:

const Loader = ({
         id = 'loader',
         inner = {
             id: 'inner',
             color: 'black'
         },
         outer = {
           id: 'outer',
           color: 'black'
         },
         ...rest
    } = {}
) => {
  return (
    <svg fill="none" viewBox="0 0 200 152" {...rest}>
      <path
        fill="none"
        id={inner.id}
        stroke={inner.color}
        d="M99.217 100.606L58.302 29.74h81.829l-40.914 70.866z"
      />
      <path
        fill="none"
        id={outer.id}
        stroke={outer.color}
        d="M100 151L13.398 1h173.205L100 151z"
      />
    </svg>
  );
};

ReactDOM.render(<Loader />, document.getElementById('root'));
<div id="root">

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>

Related