Comment gérer React Data Grid via Redux

Il s'agit d'une continuation de l'article précédent: Pourquoi écrire votre grille de données React en 2019


À quoi sert Redux? Les rĂ©ponses sont nombreuses. Par exemple, pour travailler avec des donnĂ©es partagĂ©es dans diffĂ©rents composants React. Mais vous pouvez prendre Redux comme un moyen de manipuler un composant. Le look lui-mĂȘme est intĂ©ressant: tout composant React peut contrĂŽler un autre composant React via Redux.


Prenez un composant React qui affiche les données sous forme de lignes et de colonnes (Data Grid, grid). Quelle fonctionnalité peut-elle gérer? La composition des colonnes et des lignes. Attribution. Ce serait bien de faire défiler les données.


image


Par exemple, un certain composant React (certains composants) pourrait gérer la grille comme ceci:


  • afficher ces lignes et colonnes;
  • mettre en Ă©vidence l'occurrence d'un tel mot;
  • sĂ©lectionnez une telle ligne;
  • faites dĂ©filer jusqu'Ă  une certaine ligne.

La gestion des colonnes n'est pas difficile. Il suffit de mettre les paramĂštres des colonnes dans Redux: noms, ordre, largeurs, mappage des donnĂ©es. La grille prendra ces paramĂštres et s'appliquera. L'approche des donnĂ©es est la mĂȘme.


Mais compliquons la tĂąche. Supposons qu'il y ait beaucoup de lignes. Ils ne peuvent pas ĂȘtre tĂ©lĂ©chargĂ©s Ă  partir du serveur en mĂȘme temps et ne peuvent pas ĂȘtre affichĂ©s en mĂȘme temps. Par consĂ©quent, le chargement et le mappage des donnĂ©es portionnĂ©s sont nĂ©cessaires.


Pour l'affichage des portions, nous prenons le défilement virtuel décrit dans l' article précédent . Et essayez de le croiser avec le chargement et le stockage des portions dans Redux. Nous allons également permettre à d'autres composants de manipuler les données téléchargées et de faire défiler la position via Redux.


Ce n'est pas une tùche abstraite, mais une vraie tùche du systÚme ECM que nous développons:
image


Organisez les exigences. Que voulez-vous obtenir?


  • de sorte que lors du dĂ©filement, de nouvelles donnĂ©es soient chargĂ©es;
  • pour que les donnĂ©es chargĂ©es soient dans Redux;
  • de sorte que les portions chargĂ©es peuvent ĂȘtre manipulĂ©es Ă  partir d'autres composants. Via Redux, ajoutez-supprimez-modifiez des lignes, et la grille a dĂ©tectĂ© ces changements;
  • de sorte que la position de dĂ©filement peut ĂȘtre contrĂŽlĂ©e Ă  partir d'autres composants. Dans Redux, faites dĂ©filer jusqu'Ă  la ligne souhaitĂ©e.

Nous considérerons ces tùches.


Une petite digression: le dĂ©filement virtuel de l'article prĂ©cĂ©dent vous permet de faire dĂ©filer rapidement vers n'importe quelle partie de la grille. Par exemple, Ă  la fin. La grille doit charger la derniĂšre partie des donnĂ©es, Ă  l'exclusion de toutes les donnĂ©es intermĂ©diaires, afin de ne pas extraire des milliers de lignes du serveur. Par consĂ©quent, les portions ne sont pas toujours chargĂ©es sĂ©quentiellement; elles peuvent ĂȘtre tĂ©lĂ©chargĂ©es Ă  partir de diffĂ©rentes parties de la liste.


Nous avons choisi le schéma suivant pour charger et stocker les données:
image


La grille de ce schéma est divisée en deux parties: les composants Présentation et Conteneur. La présentation ne traite que de l'affichage des données - c'est la vue. Les données sont affichées dans les pages (cela a été décrit dans un article précédent). Le conteneur est responsable du chargement des données et de l'interaction avec Redux.


Passons en revue les flĂšches du diagramme:


  1. Presentational ne charge pas les données, il indique uniquement par rappel quelles données il lui manque pour afficher. Presentational ne connaßt pas Redux, il n'effectue pas d'actions de répartition et ne se connecte pas au référentiel Redux.
  2. Le conteneur est responsable du chargement des données. Ce composant envoie une demande au serveur lors de l'appel de rappel. Un conteneur peut demander plus de données qu'il n'en doit afficher afin de minimiser le nombre de demandes au serveur.
  3. Le serveur envoie des données.
  4. Le conteneur envoie les données reçues à Redux. Redux stocke toutes les parties de données téléchargées, pas seulement la derniÚre partie téléchargée.
  5. DÚs que le prochain morceau de données entre dans Redux, le conteneur sortira tous les morceaux de Redux.
  6. Et donnez-leur une prĂ©sentation. La prĂ©sentation n'est pas nĂ©cessaire pour dessiner toutes les donnĂ©es reçues, elle affiche uniquement ce qui tombe dans la fenĂȘtre. Dans le mĂȘme temps, les donnĂ©es chargĂ©es et les pages rendues ne sont pas la mĂȘme chose. 1000 enregistrements peuvent ĂȘtre chargĂ©s dans un bloc et 50 enregistrements sont affichĂ©s sur deux pages.

Je vais donner le pseudo-code de ce schéma:


class GridContainer extends React.Component<Props> { props: Props; render(): React.Element<any> { return <Grid //     . dataSource={this.props.data} // Callback    . loadData={this.props.loadData} />; } } 

 const mapStateToProps = (state) => { return { data: state.data }; }; const mapDispatchToProps = (dispatch) => { return { loadData: async (skip: number, take: number) => { //    . const page: Page = await load(skip, take); //     Redux. dispatch({ type: ADD_PAGE, page }); } }; }; export default connect(mapStateToProps, mapDispatchToProps)(GridContainer); 

Types utilisés en pseudo-code:


 type Props = { data: DataSource, loadData: (skip: number, take: number) => void }; type DataSource = { //   . pages: Array<Page>, //    . totalRowsCount: number }; type Page = { // ,    . startIndex: number, // . rows: Array<Object> }; 

Ils ont fait face à la premiÚre tùche - charger et stocker des données dans Redux par portions. Passons maintenant à la manipulation. La tùche la plus courante consiste à ajouter-supprimer-modifier des lignes. Nous voulons que chaque composant de l'application Web puisse le faire. Le schéma est simple:


image


Certains composants sont des composants d'une application Web qui souhaitent gérer les données de la grille.


Passons en revue le schéma:


  1. Toutes les manipulations de données sont effectuées via des réducteurs Redux. Pour ajouter-supprimer-changer la ligne, il suffit de faire correspondre l'action correspondante (ADD_ROW, DELETE_ROW, UPDATE_ROW). Les réducteurs ajusteront les données dans le référentiel Redux.
  2. DÚs que les données changent dans Redux, le conteneur de grille extrait les données actuelles de Redux.
  3. Et donnez-leur une présentation. Mises à jour de présentation des pages rendues.

Défilement dans Redux


La gestion du défilement par programmation est une fonctionnalité nécessaire. La situation la plus courante consiste à faire défiler jusqu'à l'entrée en surbrillance. Par exemple, l'utilisateur crée une nouvelle entrée dans la liste. Un enregistrement avec tri se trouve au milieu de la liste. Vous devez le sélectionner par programme et le faire défiler. Et ce serait bien de le faire via Redux.


image


La gestion des sélections via Redux n'est pas difficile, mais comment contrÎlez-vous le défilement?
Pour ce faire, dans le Redux Store, nous mettrons deux champs:


  //  ,    . scrollToIndex: ?number, // ,    . scrollSignal: number 

Le champ scrollToIndex est compréhensible. Si vous souhaitez faire défiler, définissez le numéro de la ligne souhaitée dans scrollToIndex. Ce numéro sera transféré dans la grille et la grille y défilera immédiatement:


image


À quoi sert le champ scrollSignal? Il rĂ©sout le problĂšme du dĂ©filement vers le mĂȘme index. Si nous avons dĂ©jĂ  effectuĂ© le dĂ©filement du logiciel jusqu'Ă  l'index 100, le dĂ©filement vers le mĂȘme index ne fonctionnera plus. Par consĂ©quent, le champ scrollSignal est utilisĂ©, lorsqu'il est modifiĂ©, la grille dĂ©filera Ă  nouveau pour faire dĂ©filer jusqu'Ă  l'index. ScrollSignal est automatiquement incrĂ©mentĂ© dans le rĂ©ducteur lors du traitement d'une action SCROLL:


image


Pseudo-code de contrÎle de défilement:


 class GridContainer extends React.Component<Props> { props: Props; render(): React.Element<any> { return <Grid //     . dataSource={this.props.data} //  ,    .. scrollToIndex={this.props.scrollToIndex} // ,    . scrollSignal={this.props.scrollSignal} />; } } 

 const mapStateToProps = (state) => { return { data: state.data, scrollToIndex: state.scrollToIndex, scrollSignal: state.scrollSignal }; }; export default connect(mapStateToProps)(GridContainer); 

Types utilisés en pseudo-code:


 type Props = { data: DataSource, scrollToIndex: ?number, scrollSignal: number }; 

Conclusion (par Redux)


Bien entendu, les schémas d'interaction proposés avec Redux ne sont pas universels. Ils sont adaptés à la grille que nous avons développée, car nous avons optimisé la grille pour ces schémas, fait l'API appropriée pour cela. Ces schémas ne fonctionneront pour aucune grille tierce, prenez donc l'article comme exemple d'implémentation d'une interaction avec Redux.


Conclusion finale (sur les articles 1 et 2)


Lors du dĂ©veloppement de notre grille, il est venu Ă  comprendre que la grille, idĂ©alement, ne fait pas partie de notre application, mais un projet indĂ©pendant, qui mĂ©rite d'ĂȘtre publiĂ© sur github et dĂ©veloppĂ©. Par consĂ©quent, nous n'avons pas utilisĂ© les termes de notre application dans le code et ajoutĂ© des dĂ©pendances inutiles. Mais avec l'extension de la fonctionnalitĂ©, il devient de plus en plus difficile d'y adhĂ©rer, car nous ne l'avons pas allouĂ© Ă  un projet distinct, mais nous aurions dĂ» le faire tout de suite. Github est toujours dans les plans.


La rédaction de votre propre grille a été la bonne décision pour nous. Nous avons eu assez de temps pour implémenter tout ce que nous voulions (virtualisation, travail avec redux, chargement par lots, travail avec le clavier, travail avec colonnes, recherche similaire avec rétro-éclairage et bien plus). Dans un premier temps, nous avons beaucoup investi dans un réseau tiers, dans l'espoir qu'il décolle dans nos situations. En l'utilisant, nous avons compris comment les grilles fonctionnent en général, quels problÚmes existent, comment les résoudre et ce que nous voulons finalement obtenir. Et a pris sa décision.

Source: https://habr.com/ru/post/fr465585/


All Articles