I see no problem with the code, the PizzaComponent updates, changed a bit to fit React 15.5 on StackOverFlow/
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
function MyFancyComponent({label, price, value}) {
return (
<div>
{label} - {price} - {value}
</div>
);
}
function PizzaComponent(props) {
const {
size
} = props
const pizzaChoices = [
{
value: 'cheese',
label: 'Cheese',
price: '10.00',
},
{
value: 'pepperoni',
label: 'Pepperoni',
price: size,
},
];
return (
<div>
{pizzaChoices.map((choice, i) => (
<MyFancyComponent
key={`pizza-${choice.value}`}
label={choice.label}
price={choice.price}
value={choice.value}
/>
))
}
</div>
)
}
class App extends React.Component {
componentWillMount() {
this.state = {
size: 5
};
this.changeSize = this.changeSize.bind(this);
}
changeSize() {
const size = this.state.size + 5;
this.setState({ size });
}
render() {
return (
<div>
<button onClick={this.changeSize}>Change Size</button>
<PizzaComponent size={this.state.size} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
<!-- end snippet -->
There are nice answers here, and i agree with @Austin Greco (the second option with separate components) but i'm surprised no one has mentioned [currying][1].
What you can do is create a function that accept a parameter (your parameter) and returns another function that accepts another parameter (the click event in this case). then you are free to do with it what ever you want.
**ES5:**
handleChange(param) { // param is the argument you passed to the function
return function (e) { // e is the event object that returned
};
}
**ES6:**
handleChange = param => e => {
// param is the argument you passed to the function
// e is the event object that returned
};
And you will use it this way:
<input
type="text"
onChange={this.handleChange(someParam)}
/>
Here is a full example of such usage:
<!-- begin snippet: js hide: true console: true babel: true -->
<!-- language: lang-js -->
const someArr = ["A", "B", "C", "D"];
class App extends React.Component {
state = {
valueA: "",
valueB: "some initial value",
valueC: "",
valueD: "blah blah"
};
handleChange = param => e => {
const nextValue = e.target.value;
this.setState({ ["value" + param]: nextValue });
};
render() {
return (
<div>
{someArr.map(obj => {
return (
<div>
<label>
{`input ${obj} `}
</label>
<input
type="text"
value={this.state["value" + obj]}
onChange={this.handleChange(obj)}
/>
<br />
<br />
</div>
);
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
<!-- end snippet -->
Note that this approach doesn't solve the creation of a new instance on each render.
I like this approach over the other inline handlers as this one is more concise and readable in my opinion.
**Edit:**
As suggested in the comments below, you can cache / memoize the result of the function.
Here is a naive implementation:
<!-- begin snippet: js hide: true console: true babel: true -->
<!-- language: lang-js -->
let memo = {};
const someArr = ["A", "B", "C", "D"];
class App extends React.Component {
state = {
valueA: "",
valueB: "some initial value",
valueC: "",
valueD: "blah blah"
};
handleChange = param => {
const handler = e => {
const nextValue = e.target.value;
this.setState({ ["value" + param]: nextValue });
}
if (!memo[param]) {
memo[param] = e => handler(e)
}
return memo[param]
};
render() {
return (
<div>
{someArr.map(obj => {
return (
<div key={obj}>
<label>
{`input ${obj} `}
</label>
<input
type="text"
value={this.state["value" + obj]}
onChange={this.handleChange(obj)}
/>
<br />
<br />
</div>
);
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />
<!-- end snippet -->
[1]: https://www.sitepoint.com/currying-in-functional-javascript/