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>
, и асинхронно читать / писать из него.