Básicamente, los accesorios y el estado son dos formas en que el componente puede saber qué y cómo renderizar. Qué parte del estado de la aplicación pertenece al estado y cuál a alguna tienda de nivel superior está más relacionada con el diseño de su aplicación que con la forma en que funciona React. La forma más sencilla de decidir, IMO, es pensar si este dato en particular es útil para la aplicación en su conjunto, o si es información local. Además, es importante no duplicar el estado, por lo que si algunos datos pueden calcularse a partir de accesorios, deberían calcularse a partir de los accesorios.
Por ejemplo, supongamos que tiene algún control desplegable (que ajusta la selección HTML estándar para un estilo personalizado), que puede a) seleccionar algún valor de la lista yb) abrirse o cerrarse (es decir, la lista de opciones mostrada u oculta). Ahora, supongamos que su aplicación muestra una lista de elementos de algún tipo y sus controles desplegables filtran las entradas de la lista. Entonces, sería mejor pasar el valor del filtro activo como accesorio y mantener el estado abierto / cerrado local. Además, para que sea funcional, debe pasar un controlador onChange desde el componente principal, que se llamaría dentro del elemento desplegable y enviaría información actualizada (nuevo filtro seleccionado) a la tienda de inmediato. Por otro lado, el estado abierto / cerrado puede mantenerse dentro del componente desplegable, porque al resto de la aplicación realmente no le importa si el control está abierto, hasta que el usuario realmente cambie su valor.
El siguiente código no funciona completamente, necesita CSS y manejo de eventos desplegables de clic / desenfoque / cambio, pero quería que el ejemplo fuera mínimo. Espero que ayude a entender la diferencia.
const _store = {
items: [
{ id: 1, label: 'One' },
{ id: 2, label: 'Two' },
{ id: 3, label: 'Three', new: true },
{ id: 4, label: 'Four', new: true },
{ id: 5, label: 'Five', important: true },
{ id: 6, label: 'Six' },
{ id: 7, label: 'Seven', important: true },
],
activeFilter: 'important',
possibleFilters: [
{ key: 'all', label: 'All' },
{ key: 'new', label: 'New' },
{ key: 'important', label: 'Important' }
]
}
function getFilteredItems(items, filter) {
switch (filter) {
case 'all':
return items;
case 'new':
return items.filter(function(item) { return Boolean(item.new); });
case 'important':
return items.filter(function(item) { return Boolean(item.important); });
default:
return items;
}
}
const App = React.createClass({
render: function() {
return (
<div>
My list:
<ItemList items={this.props.listItems} />
<div>
<Dropdown
onFilterChange={function(e) {
_store.activeFilter = e.currentTarget.value;
console.log(_store); // in real life, some action would be dispatched here
}}
filterOptions={this.props.filterOptions}
value={this.props.activeFilter}
/>
</div>
</div>
);
}
});
const ItemList = React.createClass({
render: function() {
return (
<div>
{this.props.items.map(function(item) {
return <div key={item.id}>{item.id}: {item.label}</div>;
})}
</div>
);
}
});
const Dropdown = React.createClass({
getInitialState: function() {
return {
isOpen: false
};
},
render: function() {
return (
<div>
<select
className="hidden-select"
onChange={this.props.onFilterChange}
value={this.props.value}>
{this.props.filterOptions.map(function(option) {
return <option value={option.key} key={option.key}>{option.label}</option>
})}
</select>
<div className={'custom-select' + (this.state.isOpen ? ' open' : '')} onClick={this.onClick}>
<div className="selected-value">{this.props.activeFilter}</div>
{this.props.filterOptions.map(function(option) {
return <div data-value={option.key} key={option.key}>{option.label}</div>
})}
</div>
</div>
);
},
onClick: function(e) {
this.setState({
isOpen: !this.state.isOpen
});
}
});
ReactDOM.render(
<App
listItems={getFilteredItems(_store.items, _store.activeFilter)}
filterOptions={_store.possibleFilters}
activeFilter={_store.activeFilter}
/>,
document.getElementById('root')
);