Как записать в хранилище сеансов во время предварительной загрузки

Я знаю, что сессия в сапере - это доступный для записи магазин. Я могу написать в нем так:

<script>
    import { stores } from "@sapper/app"
    const { session } = stores()
    session.set("new value")
</script>

Однако мне трудно писать внутри функции предварительной загрузки:

<script context="module">
    export async function preload(page, session) {
        session = "new value" // not working, this is just a value, not a store
    }
</script>

Мне нужно установить там некоторые данные во время _layout.svelte предварительной загрузки. Любой поддерживаемый способ сделать это?

ИЗМЕНИТЬ. В итоге я вообще не использую сеанс, а просто хранилище с возможностью записи. Это не так чисто, но служит цели. Оставьте это открытым, если кто-то найдет способ или он получит поддержку в будущем.


person peter.babic    schedule 02.12.2019    source источник
comment
Вы можете создать свой собственный session магазин и писать в него в preload.   -  person pishpish    schedule 15.08.2020


Ответы (2)


Параметр session здесь не хранилище сеансов, это что-то еще. Об этом говорится в документации:

сеанс создается на сервере параметром сеанса, переданным в sapper.middleware (для этого нужна дополнительная документация. Возможно, раздел серверного API?)

Изменить:

[предыдущее предложение удалить, поскольку неверно]

Для полноты: session, по-видимому, относится к магазину session, аргумент - это значение магазина. Однако вы по-прежнему не можете писать в него осмысленным образом.

Как я уже сказал в комментарии, я не думаю, что то, что вы хотите делать, возможно в preload. Может, я ошибаюсь, кто-то другой может вам сказать.

Между тем, я предлагаю следующий обходной путь: проделайте все это в компоненте _layout instance. Там у вас будет полный доступ к магазинам. Примерно так:

<script>
  import { stores } from '@sapper/app'

  import { resolveAuth } from './your/utils'

  const { session } = stores()

  resolveAuth()
    .then(auth => { $session = auth })
    .catch(err => { ... })
</script>

{#if $session}
  <slot />
{:else}
  <!-- loading indicator... or not -->
{/if}

person rixo    schedule 02.12.2019
comment
Я использую этот blog.hasura.io/best-practices -of-using-jwt-with-graphql. Определить, вошел ли пользователь в систему, невозможно на сервере, поскольку он полагается на выборку клиента с httpOnly cookie. Но мне нужно сделать это до того, как будет отрисован пользовательский материал. Мне следует выбрать другой подход, пожалуйста? - person peter.babic; 02.12.2019
comment
Что ж, если вам нужно дождаться async перед рендерингом, мне это кажется допустимым вариантом использования. - person rixo; 02.12.2019
comment
При тестировании кода, который вы предоставили, stores определен, а stores.session - нет. Обратите внимание, что я не вносил никаких изменений в server.js, так что это может быть причиной. - person peter.babic; 02.12.2019
comment
Да, вы правы, я некорректно тестировал этот код. Вы не можете разрешить хранилища из сценария context=module, а только в обычном сценарии (т.е. экземпляре компонента). Кроме того, аргумент сеанса - это только значение объекта сеанса, а не хранилище, поэтому вы не можете писать в него. Я не думаю, что можно делать то, что вы хотите, в функции preload. - person rixo; 03.12.2019
comment
Хорошо, я даю вам голос за ваше мнение, думаю, что это невозможно, но, если я не ошибаюсь, ваш код, к сожалению, не сильно отличается от того, что я представил в вопросе. - person peter.babic; 03.12.2019
comment
Да, в самом деле. Вы получите пустую страницу вместо того, чтобы оставаться на предыдущей во время загрузки с этим. Если это вариант, вы можете установить значение объекта сеанса с сервера с помощью промежуточного программного обеспечения. - person rixo; 03.12.2019

Как уже упоминалось, переменная сеанса в предварительной загрузке не совпадает с вашим хранилищем сеансов ... они просто имеют одно и то же имя, и это работает, потому что они изолированы по области видимости друг от друга.

Функция предварительной загрузки, предоставляемая sapper, работает как на клиенте, так и на сервере, тогда как хранилища - поскольку они являются частью svelte - существуют только на клиенте, поэтому импорт хранилища в предварительную загрузку невозможен, насколько я понимаю. осведомленный.

В моем случае при первом посещении моего приложения я хотел обновить сеанс, если сеанс уже существовал для клиента, с помощью файла cookie HttpOnly. Для меня наиболее очевидным местом для жизни этого кода является файл _layout.svelte.

Мое обходное решение заключалось в том, чтобы создать переменную currentSession и присвоить ей данные сеанса следующим образом:

<script context="module">
    export async function preload(page, session) {
        let currentSession = session;
        return { currentSession };
    }
</script>

Затем в моем основном теге скрипта

<script>
export let currentSession; // <-- Needs export because it's a prop.
import { session } from '../stores.js';
session.set(currentSession);

// ...Do more stuff...
</script>

Это не идеальный вариант - мы оба хотим - а именно, переменная сеанса уже существует как хранилище с данными сеанса при импорте, но я думаю, это следующий лучший вариант. Основное преимущество заключается в том, что если вы инициализируете свои хранилища чем-то вроде let session = writeable(null);, тогда $session больше не будет null к моменту загрузки вашего компонента.

Если вы придумали лучший способ, дайте мне знать. Спасибо.

person Levi Mootz    schedule 15.12.2020