Bonjour,
Je débute avec React js et javascript globalement après avoir développé pendant longtemps en java EE
Mon problème porte sur l'organisation et le découpage de mes codes
En effet, mon application est fait d'un ensemble de formulaires, ici je prendrais un cas typique de la fonctionnalité qui fait du CRUD sur une entité nomée societe
J'ai crée deux composants SocieteForm et SocieteList (j'espère que les nom sont parlant). Afin d'avoir un code clair et lisible, je crée une classe ManagedSociete qui contiendra la logique de mon application
voici à quoi resemble le code final

export default function SocieteList(){
    const service=new ManagedSociete();
    const [societes, setSocietesList]=useState<Array<ISociete>>(service.societes);
    useEffect(()=>{
        setSocietesList(service.getSocietes());
    },[service.societes.length])
    const columns:GridColDef[]=[
        {field:"id", headerName:"Id", width:50},
        {field:"name", headerName:"Raison social", width:150}
    ];
    return(
         <div className="form_societe">
             <h1>Liste des sociétés <Button className="menu-list" component={Link}          to="/societe/form">Revenir au formulaire</Button></h1>
            <DataGrid
                columns={columns}
                rows={societes}
                 autoHeight={true} />
         </div>
    )
export default function SocieteForm(){
    const {register, handleSubmit}=useForm<ISociete>();
    const service=new ManagedSociete();
    const saveForm:SubmitHandler<ISociete>=(data)=>{
    //on invoque la fonction save depuis notre classe service
        service.saveSociete(data);
    }
    return(
        <div className="form_societe" onSubmit={handleSubmit(saveForm)}>
            <h1>Formulaire société
                <Button className="menu-list" component={Link} to="/societe/list"
                 >Voir la liste</Button>
            </h1>
            <form className="fomulaire " >
                <Grid container spacing={2} justifyContent="space-between">
                    <Grid item md={10} xs={10}>
                        <TextField label="Désignation" variant="filled" color="primary" focused
                        fullWidth  {...register("name")}/>
                    </Grid>
                    <Grid item md={2} xs={2}>
                        <TextField label="Forme Juridique" variant="filled"
                                   fullWidth {...register("formeJuridique")} />
                    </Grid>
                    <Grid item  >
                       <Button variant={"contained"} type={"submit"}>Enregistrer</Button>
                    </Grid>
                </Grid>
            </form>
        </div>
    )
import {ISociete} from "./ISociete";

export class ManagedSociete{
    private societe:ISociete;
    societes=new Array<ISociete>();

    saveSociete(societe:ISociete){
        this.societes.push(societe)
    }

    getSocietes():Array<ISociete>{
        return this.societes;
    }

}

Ce que je veux
Je voudais pouvoir modifier le state de mon composant SocieteList avec la liste societes (déclarer dans ma classe ManagedSociete ) et invoqué depuis le composant SocieteForm

J'aimerais également savoir si cette architechture convient dans le monde javascript/React

Merci d'avance pour vos réponses

5 réponses


Alors la tu as modifié l'instance de Societe invoquée par ManagedSociete
Du coup pour voir la différence il faudrait que ta vue passe par ManagedSociete qui afficherait le composant global Societe

const listSociete = this.societes.map(societe => <Societe key={societe.id} societe={societe} />) // key ce n'est pas un argument de ton component, c'est pour dire a react qu'il y'a une liste de societes et qu'il n'a pas besoin de paniquer (parce qu'il va paniquer en voyant une liste du même component :p)

return (
    <>
        <div>blabla</div>

        { $listSociete }

        <div>blabla</div>
    </>
)

Grossièrement ce serait ça dans le render de managedSociete

Ensuite ManagedSociete devrait plutot être une page (SocietesPage), alors que Societe devrait juste etre des components

gouchere
Auteur

Merci Popotte pour ta réponse rapide,
si je fais de ManagedSociete une page, je vais devoir annuler SocieteForm et je pense que le problème restera le même (gros formulaire avec beaucoup de code)
j'ai fais des lectures où on parle de Contexte, et aussi de Redux. Ma solution peut-elle s'y trouver? et si oui, est-ce que Redux est approprié pour garder de nombreuse grosses listes de données d'application qu'on va partager sur plusieurs pages de l'application?

Avec plaisir ;)

Alors non tu n'as pas besoin de mettre directement le from dans la page, ta page peut appeler la form exportée dans un component

return (
    <>
        <SocieteForm args={args} />
    </>
)

Et c'est plié :p

Alors Redux c'est une solution, tu récupères les données depuis la base de données et voila

Mais ce serait plus simple de passer par NextJS (en gros c'est la version "framework" de ReactJS (React c'est une librairie à implémenter dans un autre framework à la base))

gouchere
Auteur

Je viens partager avec vous la suite de mon problème.
J'ai atteint mon objectif en définissant dans mon fichier ManagedSociete.tsx ainsi

import {ISociete} from "./ISociete";

/**je fais ma liste une variable globale**/
 export const societes=new Array<ISociete>();
export class ManagedSociete{
    private societe:ISociete;

    saveSociete(societe:ISociete){
        this.societes.push(societe)
    }

    getSocietes():Array<ISociete>{
        return this.societes;
    }

}

Je rappelle que mon objectif était de sortir la logique applicative de mes composant pour être capable de changer les composant plus tard sans toucher à cette logique forcement.
Alors peut-être je m'y prend mal en tant que débutant react. J'aimerai encore avoir votre point de vue là.
Merci.

Hello,

C'est quelques chose que je n'ai pas encore rencontré malgré beaucoup de lecture concernant le sujet React.

Je penses que ton approche peut fonctionner, meme si pour ma part je passerai tout en fonctionnel.

En revanche comme popotte pour moi ManagedSociete devrait être une page et c'est ici que la logique applicative ce fera.

par exemple si je reprend t'es lignes de codes.

Je transformerai les choses comme ceci. ( après faut voir comment est ta vue, cela ne conviendra peut être pas )

import React, {useCallback} from "react";
import {ISociete} from "./ISociete";

export const ManagedSociete = () => {
    const [societes, setSocietes ] = useState<ISociete[]>([])

    const saveSociete = useCallback((societe:ISociete) => {
       setSocietes([...societes, societe])
    },[])

    return (
        <>
            <SocieteForm saveSociete={saveSociete}/>
            <SocieteList societes={societes} />
        </>
    )
}
export default function SocieteForm({saveSociete}){
    const {register, handleSubmit}=useForm<ISociete>();

    return(
        <div className="form_societe" onSubmit={handleSubmit(saveSociete)}>
            <h1>Formulaire société
                <Button className="menu-list" component={Link} to="/societe/list"
                 >Voir la liste</Button>
            </h1>
            <form className="fomulaire " >
                <Grid container spacing={2} justifyContent="space-between">
                    <Grid item md={10} xs={10}>
                        <TextField label="Désignation" variant="filled" color="primary" focused
                        fullWidth  {...register("name")}/>
                    </Grid>
                    <Grid item md={2} xs={2}>
                        <TextField label="Forme Juridique" variant="filled"
                                   fullWidth {...register("formeJuridique")} />
                    </Grid>
                    <Grid item  >
                       <Button variant={"contained"} type={"submit"}>Enregistrer</Button>
                    </Grid>
                </Grid>
            </form>
        </div>
    )
export default function SocieteList({societes}){

    const columns:GridColDef[]=[
        {field:"id", headerName:"Id", width:50},
        {field:"name", headerName:"Raison social", width:150}
    ];

    return(
         <div className="form_societe">
             <h1>Liste des sociétés <Button className="menu-list" component={Link} to="/societe/form">Revenir au formulaire</Button></h1>
            <DataGrid
                 columns={columns}
                 rows={societes}
                 autoHeight={true} 
             />
         </div>
    )

Au pire si ça te dérange d'avoir des composants dans ManagedSociete, tu fais un custom Hooks

import React, {useCallback} from "react";
import {ISociete} from "./ISociete";

export const useManagedSociete = () => {
    const [societes, setSocietes ] = useState<ISociete[]>([])

    const saveSociete = useCallback((societe:ISociete) => {
       setSocietes([...societes, societe])
    },[])

    return {societes, setSocietes, saveSociete}
}

et apres tu l'invoque la ou tu en a besoin et ta logique applicative reste aussi au meme endroit.

exemple

import {useManagedSociete} from "../hooks"

export default function SocieteList(){

    const {societes} = useManagedSociete()

    const columns:GridColDef[]=[
        {field:"id", headerName:"Id", width:50},
        {field:"name", headerName:"Raison social", width:150}
    ];

    return(
         <div className="form_societe">
             <h1>Liste des sociétés <Button className="menu-list" component={Link} to="/societe/form">Revenir au formulaire</Button></h1>
            <DataGrid
                 columns={columns}
                 rows={societes}
                 autoHeight={true} 
             />
         </div>
    )