Introduction
I had this code:
import React, { Component } from 'react';
import { View, Button } from 'react-native';
export default function App() {
const myMethod = (name) => {
console.log(`Hello ${name}!`);
};
return (
<View>
<Button onPress={() => myMethod("Victor")}>
Press me!
</Button>
</View>
);
}
Then, I decided to refactor it using the carried functions
pattern. Like this:
import React, { Component } from 'react';
import { View, Button } from 'react-native';
export default function App() {
/**
* @param {string} name - The name.
* @returns {Function} Curried function.
*/
const myMethod = (name) => {
return () => {
console.log(`Hello ${name}!`);
}
};
return (
<View>
<Button onPress={myMethod("Victor")}>
Press me!
</Button>
</View>
);
}
As you can see, the way I am invoking the method has changed, as I am returning a function
instead of void
in myMethod
. That's cool, it works... every time the button is pressed, my method is invoked.
Check this snack: https://snack.expo.dev/Rx3iBVT_W
Problem
Now, I am trying to refactor the refactored code using the curry
api from lodash
.
This is what I have tried:
import React, { Component } from 'react';
import { View, Button } from 'react-native';
import { curry } from 'lodash';
export default function App() {
const myMethod = curry((name) => {
console.log(`Hello ${name}!`);
});
return (
<View>
<Button onPress={myMethod("Victor")}>
Press me!
</Button>
</View>
);
}
But for some reason, this is not working. The method is not executed every time the button is pressed... Instead, it is invoked when the component mounts.
How can I solve it?
Check this snack: https://snack.expo.dev/bna6cLkhp
CodePudding user response:
I'm afraid you've misunderstood currying (which is easily done, and lots have — including myself).
Then, I decided to refactor it using the carried functions pattern. Like this:
That code doesn't curry a function. It just creates a closure over the name
parameter. That's called partial application.
Lodash's curry
does currying instead. The function it returns will do its work as soon as all of its parameters are satisfied — as soon as you provide it the name it needs, in your case. So it does its work when you do myMethod("Victor")
, not later:
const myMethod = _.curry((name) => {
console.log(`Hello ${name}!`);
});
myMethod("Victor");
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
If you want it to wait for a second argument, you need to tell curry
that your function requires two arguments, and then provide it with two arguments (one at a time in this case):
const myMethod = _.curry((name) => {
console.log(`Hello ${name}!`);
}, 2);
// ^−−−−−−− tells `curry` this function needs two arguments, even
// though the function itself says it only needs 1
console.log("Supplying the first argument");
const fn = myMethod("Victor");
console.log("Supplying the second argument");
fn({}); // <== Note the argument, we need to supply one
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
That works because we've told curry
your function needs to have two arguments, and myMethod("Victor")
only gives it one, so it returns another function that will do its work when you give it the other argument. onPress
will give it a second argument because it passes the event object to it.
Check out the curry
documentation for more examples.
That said, I wouldn't use curry
here. You're not really currying, so it's a bit of a misuse. I'd use your partial application solution, if I had to bake the name into the function at all.