Reputation: 3221
What is the canonical React+Flux way to ID components that trigger changes to state?
I've got an application that allows a user to create palettes using the HSL color space.
Here's the component structure of my app:
Container (this component gets state and passes it down the chain)
| PalettePicker
| ColorPicker
| Slider (this component fires action)
| Slider
| Slider
| (As many ColorPickers as colors)
| ImageSamples (not relevant, but dependent on palette)
Here's a look at the ColorPicker
component:
Each ColorPicker
contains 3 Slider
components which trigger events that update the store. The store then updates the palette and passes the entire palette down to the Container
component, which passes it down as props
to its children components.
Here's my function that handles a slider change event in my Store
(I'm using Reflux):
sliderChange: function(newValue) {
var modifiedPalette = this.palette;
modifiedPalette[newValue.colorIndex][newValue.colorPartsIndex] = newValue.value;
this.trigger(modifiedPalette)
}
My palette is an array of HSL color values, so something like:
[ [350, 100, 50], [340, 100, 40], ... ]
A "color" is one of the 3-item arrays above and I'm calling each item in the color array a "color part" since it represents either the H, S, or L of the color.
Passing the color and color part index down as a prop seems inelegant. I'm currently building components like this:
colorPickers = palette.map(function(color, i) {
return (
<ColorPicker
key={i}
colorIndex={i}
color={color}
/>
)
});
As far as I can tell, I need to pass colorIndex
as a prop so that my child component can know which color in the palette it maps to so that I can pass that knowledge on to the store.
What's the idiomatic React+Flux way to do this?
Upvotes: 1
Views: 340
Reputation: 6222
I would suggest not letting the ColorPicker component call any action itself, but pass it as an "onChange" prop. It doesn't need to know what index it is. You can bind the onChange function so that it will pass the index:
colorPickers = palette.map(function(color, i) {
return (
<ColorPicker key={i}
onChange={this.changeColor.bind(this, i)}
color={color}
/>
)
});
The changeColor function looks like this:
changeColor : function(colorIndex, colorArray) {...}
It should receive the whole color (the array) and fire the appropriate Reflux action with it and the index. That way the ColorPicker only have to fire the onChange function with the new color that changed.
Do the same trick for every slider inside the color picker. Pass it an onChange function that is already bounded to its partIndex. When that function is triggered, The ColorPicker should construct a new color array, and call its own onChange prop.
Hope it was clear enough. The motivation is - every component should get a simple callback function and output only what it is responsible for. It doesn't need to know any other details. Instead of passing more and more useless index props all the way down, just pass bounded callbacks. It will simplify your components and will let your high-level component deal with the details of constructing the Flux action itself.
Upvotes: 1