Estoy reescribiendo mi aplicación para usar Flux y tengo un problema con la recuperación de datos de las tiendas. Tengo muchos componentes y anidan muchos. Algunos de ellos son grandes ( Article
), otros son pequeños y simples ( UserAvatar
, UserLink
).
He estado luchando con el lugar de la jerarquía de componentes en el que debería leer los datos de las tiendas.
Probé dos enfoques extremos, ninguno de los cuales me gustó del todo:
Todos los componentes de la entidad leen sus propios datos
Cada componente que necesita algunos datos de la Tienda recibe solo el ID de entidad y recupera la entidad por sí misma.
Por ejemplo, Article
se pasa articleId
, UserAvatar
y UserLink
se pasan userId
.
Este enfoque tiene varias desventajas importantes (discutidas en el ejemplo de código).
var Article = React.createClass({
mixins: [createStoreMixin(ArticleStore)],
propTypes: {
articleId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
article: ArticleStore.get(this.props.articleId);
}
},
render() {
var article = this.state.article,
userId = article.userId;
return (
<div>
<UserLink userId={userId}>
<UserAvatar userId={userId} />
</UserLink>
<h1>{article.title}</h1>
<p>{article.text}</p>
<p>Read more by <UserLink userId={userId} />.</p>
</div>
)
}
});
var UserAvatar = React.createClass({
mixins: [createStoreMixin(UserStore)],
propTypes: {
userId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
user: UserStore.get(this.props.userId);
}
},
render() {
var user = this.state.user;
return (
<img src={user.thumbnailUrl} />
)
}
});
var UserLink = React.createClass({
mixins: [createStoreMixin(UserStore)],
propTypes: {
userId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
user: UserStore.get(this.props.userId);
}
},
render() {
var user = this.state.user;
return (
<Link to='user' params={{ userId: this.props.userId }}>
{this.props.children || user.name}
</Link>
)
}
});
Desventajas de este enfoque:
- Es frustrante tener componentes de 100 que potencialmente se suscriban a las tiendas;
- Es difícil hacer un seguimiento de cómo se actualizan los datos y en qué orden porque cada componente recupera sus datos de forma independiente;
- Aunque es posible que ya tenga una entidad en estado, se ve obligado a pasar su ID a los niños, quienes la recuperarán nuevamente (o romperán la consistencia).
Todos los datos se leen una vez en el nivel superior y se transmiten a los componentes
Cuando estaba cansado de rastrear errores, traté de poner toda la recuperación de datos en el nivel superior. Sin embargo, esto resultó imposible porque para algunas entidades tengo varios niveles de anidación.
Por ejemplo:
- A
Category
contieneUserAvatar
s de personas que contribuyen a esa categoría; - An
Article
puede tener variosCategory
s.
Por lo tanto, si quisiera recuperar todos los datos de las tiendas al nivel de an Article
, necesitaría:
- Recuperar artículo de
ArticleStore
; - Recuperar todas las categorías de artículos de
CategoryStore
; - Recupere por separado los contribuyentes de cada categoría de
UserStore
; - De alguna manera, transfiera todos esos datos a los componentes.
Aún más frustrante, siempre que necesite una entidad profundamente anidada, necesitaría agregar código a cada nivel de anidación para transmitirlo adicionalmente.
Resumiendo
Ambos enfoques parecen defectuosos. ¿Cómo soluciono este problema de la manera más elegante?
Mis objetivos:
Las tiendas no deberían tener una cantidad increíble de suscriptores. Es estúpido que cada uno
UserLink
escucheUserStore
si los componentes principales ya lo hacen.Si el componente principal ha recuperado algún objeto de la tienda (por ejemplo
user
), no quiero que ningún componente anidado tenga que recuperarlo de nuevo. Debería poder pasarlo a través de accesorios.No debería tener que buscar todas las entidades (incluidas las relaciones) en el nivel superior porque complicaría agregar o eliminar relaciones. No quiero introducir nuevos accesorios en todos los niveles de anidación cada vez que una entidad anidada obtiene una nueva relación (por ejemplo, la categoría obtiene una
curator
).