Svelte проблема регистрации пользователя с установкой значения магазина

Привет :)

Я пытаюсь зарегистрировать пользователя и после успеха устанавливаю контекст для нового зарегистрированного пользователя, а затем перехожу на главную. Сервер правильно отвечает и регистрирует пользователя, но при вызове setContext я получаю следующую ошибку: "index.mjs:552 Uncaught (in prom) Ошибка: функция вызвана внешней инициализацией компонента"

    <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>

Что я делаю неправильно?

1 ответ

Решение

setContextдолжен вызываться синхронно во время инициализации компонента. То есть из корня<script> тег:

<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>

Об этом говорится в небольшом загадочном предложении в документации:

Как и функции жизненного цикла, это должно вызываться во время инициализации компонента.

Другие функции жизненного цикла: onMount, onDestroyи т. д. Возможно, менее очевидно, что setContext такой метод жизненного цикла.

редактировать

Я просто перечитал ваш вопрос и понял, что это действительно ответ на половину...

setContext / getContextможно использовать только один раз при инициализации компонента, так как же передать результат API через контекст? Связано: как бы вы поделились этими результатами API, если бы вызов был сделан вне компонента Svelte, гдеsetContext было бы даже более неприемлемым (и, возможно, вызов API был бы лучше расположен для разделения вопросов)?

Хорошо, поместите магазин в свой контекст.

Например, с магазином с возможностью записи:

<script>
  import { getContext } from 'svelte'

  const userData = getContext('userData')

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

Поместите это хранилище в контекст во время инициализации некоторого более высокого компонента оболочки (например, <App>):

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

  const userData = writable(null)

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

<slot />

Таким образом, вы можете легко получить доступ к своему магазину с помощью getContext из любого дочернего компонента (скажем) <App>, и асинхронно читать / писать из него.

Другие вопросы по тегам