Ошибка регистрации пользователя Svelte с настройкой значения магазина - PullRequest
1 голос
/ 08 марта 2020

helo:)

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

    <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 Ответ

3 голосов
/ 09 марта 2020

setContext должен вызываться синхронно во время инициализации компонента. То есть из root тега <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>

Это упоминается в небольшом предложении crypti c в документах :

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

Другими функциями жизненного цикла являются onMount, onDestroy, et c. Возможно, менее очевидно, что setContext - это такой метод жизненного цикла.

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

Я просто перечитал ваш вопрос и понял, что на самом деле просто отвечаю на половину. ..

setContext / getContext можно использовать только один раз в компоненте init, так как вы делитесь результатами 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>, и читать / писать из него асинхронно.

...