Skip to content
This repository has been archived by the owner on Sep 10, 2022. It is now read-only.

[Question] Clarification of example. #5

Closed
richardvanbergen opened this issue Oct 8, 2015 · 3 comments
Closed

[Question] Clarification of example. #5

richardvanbergen opened this issue Oct 8, 2015 · 3 comments

Comments

@richardvanbergen
Copy link

Sorry to ask you this directly but would you mind clarifying a bit of your example?

mapProps(({ setCounter, ...rest }) => ({
  increment: () => setCounter(n => n + 1),
  decrement: () => setCounter(n => n - 1),
  ...rest
 }))

So far I have this when translated to ES5 by hand.

mapProps(function({setCounter: setCounter, /* ...rest??? */})) {
  return {
    increment: function() { return setCounter(n => n + 1) },
    decrement: function() { setCounter(n => n - 1) },
    // ...rest?????
  }
})

I have three questions.

  1. Is this reasonably accurate?
  2. I get that ...will spead the values in restinto the object but I'm really confused as to where rest comes from.
  3. Why are the arguments wrapped in an object literal? I'm sure I've translated this part poorly.

I don't think many people will find it easy to understand what this example does. Might want to cool it with the ({(({}) => ({}))}) and some of the more advanced ES2015 features.

Many thanks.

@acdlite
Copy link
Owner

acdlite commented Oct 8, 2015

Thanks for the feedback!

  1. It's pretty close. The return isn't really needed. You're using arrow functions inside setCounter(), which isn't ES5. The arguments list is wrong, which I'll address below.
  2. The props mapper receives a single argument: the props passed down from the owner. In this case, the props are counter, setCounter, and whatever additional props are passed to <CounterContainer> So if the owner renders <CounterContainer foo="bar" bar="baz" />, then ...rest is an object containing counter, foo, and bar.
  3. This is taking advantage of object destructuring inside the arguments list.

The fixed ES5 example looks like this:

mapProps(function(props) {
  return Object.assign({}, props, {
    increment: function() { props.setCounter(function(n) { return n + 1; }); },
    decrement: function() { props.setCounter(function(n) { return n - 1; }); },
  });
})

As you can see, ES2015 features make a big difference here, especially arrow functions. I think it's fairly safe to assume that most people who would be interested in using Recompose will be mostly familiar with ES2015 features, since Babel is the official solution for compiling JSX.

However, I agree with you that for someone who's not as familiar with things like ES2015, or currying, or function composition, or higher-order components... it may be all a bit overwhelming. Perhaps when I have the time to build a proper docs site, we can do something similar to what @gaearon did with his code snippets for React DnD, which can be toggled between ES5/ES6/ES7.

@acdlite acdlite closed this as completed Oct 8, 2015
@queckezz
Copy link

queckezz commented Oct 8, 2015

This is pretty accurate, yes. You can't return an object inline with arrow functions since the compiler can't differentiate between { as the start of an object literal or the start of the function body. To get around that you wrap it in ():

// won't work
const vector = (x, y) => { x, y }

//works
const vector = (x, y) => ({ x, y })

The Notion function({ setCounter, ...reset }) is called destructuring in ES2015. Basically instead of doing

mapProps(function(props) {
  var setCounter = props.setCounter
  var rest = Array.prototype.slice.call(arguments, 1); // rest of the properties of `props`
})

You can just get the properties you want to modify and create a new object that merges the existing properties with the modified ones.

If it helps, here would be the ES5 non-immutable way:

mapProps(function(props) {
  var setCounter = props.setCounter

  var decrement = function () {
    setCounter(function (n) {
        return n - 1
    })
  }

  var increment = function () {
    setCounter(function (n) {
        return n + 1
    })
  }

  props.increment = increment
  props.decrement = decrement
  return props
})

@acdlite
Copy link
Owner

acdlite commented Oct 8, 2015

@queckezz Ooh, I know you're trying to be helpful, but please don't modify the props object, even in an example. Don't want anyone to get confused and think that's okay :)

Here's that snippet updated to use a new object:

mapProps(function(ownerProps) {
  var setCounter = ownerProps.setCounter

  var decrement = function () {
    return setCounter(function (n) {
        return n - 1
    })
  }

  var increment = function () {
    return setCounter(function (n) {
        return n + 1
    })
  }

  var props = {}
  props.increment = increment
  props.decrement = decrement
  return props
})

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants