3 votes

Problème d'enregistrement de l'utilisateur de Svelte avec le réglage de la valeur de la boutique

Helo :)

J'essaie d'enregistrer un utilisateur et, après avoir réussi, de définir le contexte de l'utilisateur nouvellement enregistré, puis de naviguer vers l'accueil. Le serveur répond correctement et enregistre l'utilisateur, mais lorsque setContext est appelé, je reçois l'erreur suivante : "index.mjs:552 Uncaught (in promise) Error : Function called outside component initialization"

    <script>
    import { setContext } from 'svelte'

    async function handleRegistration(e) {
        let user = {
                    firstname: e.target.firstname.value,
                    lastname: e.target.lastname.value,
                }

                fetch('http://localhost:3001/api/auth/register', {
                    method: 'POST',
                    headers: {'Content-Type':'application/json'},
                    body: JSON.stringify(user)
                })
                .then(res => res.json())
                .then(res => {
                    if(res.accessToken) {
                        user.accessToken = res.accessToken
                        user.refreshToken = res.refreshToken
                        setContext('userData', user)
                        navigate("/", { replace: true })
                    }
                })

                updateContext(user)
            }
    }
</script>

<form class="registration" on:submit|preventDefault="{handleRegistration}">
</form>

Qu'est-ce que je fais de mal ?

9voto

rixo Points 9035

setContext doit être appelé de manière synchrone pendant l'initialisation du composant. C'est-à-dire, à partir de la racine du <script> étiquette :

<script>
  import { setContext } from 'svelte'

  console.log('init')

  setContext(...) // OK

  setTimeout(() => {
    setContext(...) // Not OK (we're not synchronous anymore)
  }, 0)
<script>

<h1>My Svelte Component</h1>

Cela est mentionné dans une petite phrase énigmatique dans la docs :

Comme les fonctions de cycle de vie, elle doit être appelée pendant l'initialisation du composant.

Les autres fonctions du cycle de vie sont onMount , onDestroy etc. Il est sans doute moins évident que setContext est une telle méthode de cycle de vie.

Modifier

Je viens de relire ta question, et j'ai réalisé que ça ne répondait qu'à la moitié de la question...

setContext / getContext ne peut être utilisé qu'une seule fois lors de l'initialisation du composant, alors comment partager le résultat de votre API par le biais du contexte ? Dans le même ordre d'idées, comment partager les résultats de l'API si l'appel a été effectué en dehors d'un composant Svelte, dans lequel setContext serait encore plus hors de question (et l'appel API serait sans doute mieux situé, pour des questions de séparation des préoccupations) ?

Eh bien, mettez un magasin dans votre contexte.

Par exemple, avec un magasin inscriptible :

<script>
  import { getContext } from 'svelte'

  const userData = getContext('userData')

  function handleRegistration(e) {
    doSuperApiCall()
      .then(data => {
        userData.set(data)
        // or fancy:
        $userData = data
      })
      .catch(...)
  }
</script>
...

Placez ce magasin dans le contexte de l'init d'un composant supérieur de conditionnement (comme le <App> ) :

<script>
  import { setContext } from 'svelte'
  import { writable } from 'svelte/store'

  const userData = writable(null)

  setContext('userData', userData)
</script>

<slot />

De cette façon, vous pouvez facilement accéder à votre magasin avec getContext de tout composant enfant de (disons) <App> et y lire/écrire de manière asynchrone.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X