0

我熟悉 Svelte,但对 Sveltekit 完全陌生。我正在尝试使用 AWS Cognito 作为授权工具从头构建一个 Sveltekit 应用程序,而不使用 AWS Amplify,使用amazon-cognito-identity-jssdk。就登录、注册和验证而言,我已经拥有了所有功能,但我似乎无法掌握如何为我构建的结构存储会话数据。

我一直在尝试将本教程中的策略(基于 React)翻译为 Sveltekit——(AWS Cognito + React JS 教程 - 会话和注销 (2020) [Ep. 3])https://www.youtube。 com/watch?v=R-3uXlTudSQ 和这个 REPL 来理解在 Svelte 中使用上下文([AD] 将上下文 API 与 Stores 结合)https://svelte.dev/repl/7df82f6174b8408285a1ea0735cf2ff0

详细地说,我的结构是这样的(仅显示重要部分):

src
|
|-- components
    |-- ...
    |-- status.svelte
|-- routes
    |
    |-- dashboard
    |-- onboarding
        |-- __layout.reset.svelte
        |-- login.svelte
        |-- signup.svelte
        |-- verify.svelte
        |-- ...
    |-- settings
    |-- __layout.svelte
    |-- index.svelte
|-- styles
|-- utils
    |-- cognitoTools.ts
    |-- stores.ts

我想为我的入职页面设置一个单独的路径,因此是子文件夹。我基于认知的功能驻留在cognitoTools.ts. 一些函数的示例如下所示:

export const Pool = new CognitoUserPool(poolData);

export const User = (Username: string): any => new CognitoUser({ Username, Pool });

export const Login = (username: string, password: string): any => {
    return new Promise ((resolve, reject) => User(username).authenticateUser(CognitoAuthDetails(username, password), {
        onSuccess: function(result) {
            console.log('CogTools login success result: ', result);
            resolve(result)
        },
        onFailure: function(err) {
            console.error('CogTools login err: ', err);
            reject(err)
        }
    }))
}

然后我可以在任何地方自由使用这些方法:

// src/routes/onboarding/login.svelte
import { Login, Pool } from '@utils/cognitoTools'
import { setContext, getContext } from 'svelte'

let username;
let password;
let session = writeable({});
let currentSession;

// Setting our userSession store to variable that will be updated
$: userSession.set(currentSession);

// Attempt to retrieve getSession func defined from wrapper component __layout.svelte
const getSession = getContext('getSession');

const handleSubmit = async (event) => {
    event.preventDefault()
        
    Login(username, password, rememberDevice)
    .then(() => {
        getSession().then((session) => {
            // userSession.set(session);
            currentSession = session;
            setContext('currentSession', userSession);
        })
    })
}
...

// src/routes/__layout.svelte
    ...
    const getSession = async () => {
        return await new Promise((resolve, reject) => {
            const user = Pool.getCurrentUser();
            
            if (user) {
                user.getSession((err, session) => {
                    console.log('User get session result: ', (err ? err : session));
                    err ? reject() : resolve(session);
                });
            } else {
                console.log('get session no user found');
                reject();
            }
        })
    }

    setContext('getSession', getSession)

然后,我一直试图在src/components/status.svelteor中检索会话src/routes/__layout.svelte(我认为我理解必须在顶级组件中设置上下文,然后可以由间接子组件使用)来检查上下文是否设置正确。

就像是:


let status = false;

const user = getContext('currentSession');

status = user ? true : false;

我在兜圈子,我知道我离答案很近了。如何在当前文件结构中使用反应式上下文来完成此任务?

4

1 回答 1

0

我不知道你到底遇到了什么问题,但对我来说突出的一件事是你在setContext“为时已晚”时打电话。您只能在组件初始化中调用getContext/ 。setContext有关更多详细信息,请参阅此答案:Is there a way to use svelte getContext etc. svelte functions in Typescript files?

如果这是罪魁祸首,并且您正在寻找一种获取会话的方法,那么:将上下文与商店结合使用:

<!-- setting the session -->
<script>
  // ...
  const session = writable(null);
  setContext('currentSession', session);
  // ...
  Login...then(() => ...session.set(session));
</script>

<!-- setting the session -->
<script>
  // ..
  const user = getContext('currentSession');
  // ..
  status = $user ? true : false;
</script>

对我来说突出的另一件事 - 但对于 StackOverflow 答案来说太长/太模糊了 - 是您没有使用 SvelteKit 的功能来实现此行为。您可以查看load并使用stuffin__layout将会话传递给所有孩子。我不确定这是否对您有任何好处,因为您可能正计划做一个 SPA,因此不需要这样的 SvelteKit 功能。

于 2022-01-25T07:37:32.973 回答