是否可以调用一个异步函数,在JS类的构造函数中获取初始数据?



我正在用Mobx和Mobx React Lite构建一个示例应用程序,以学习如何使用这个状态管理库。当用户访问页面时,应用程序需要加载问题。在构造函数中像这样调用初始加载的数据可以吗?这会导致bug吗?

我担心的是它可能会再次取回,但我不确定这可能是我唯一应该担心的。

如果有风险,你建议其他的模式吗?

我的另一个想法是,当他们点击"开始测试"时,把它从上下文中抓取出来。按钮,并有一个加载屏幕,而它获取数据。这是最有可能发生的事情,但我或多或少只是想知道我所做的是否也很好。

import { observable, action } from "mobx";
import { getQuestions } from "../api/api";
export interface Question {
category: string;
type: string;
question: string;
correct_answer: string;
incorrect_answers: string[];
}
export class TriviaStore {
constructor() {
// Is this bad?
(async() => {
await this.loadQuestions();
})()
}
@observable questions: Question[] = [];
@observable currentQuestion: number = 0;
@action
async loadQuestions() {
let questions: Question[] = await getQuestions();
this.questions = questions;
}
@action
nextQuestion() {
this.currentQuestion++;
}
}

存储只在上下文提供程序中实例化一次,如下所示:

import React from 'react';
import { TriviaStore } from '../stores/TriviaStore';
/**
* Store Types.
* Add any new stores here so the context type is updated.
*/
type RootStateContextValue = {
triviaStore: TriviaStore;
}
const RootStateContext = React.createContext<RootStateContextValue>({} as RootStateContextValue);
/**
* Stores
* Use this area to create instances of stores to pass down.
*/
const triviaStore = new TriviaStore();
/**
* Root State Provider
* @returns global state context wrapper.
*/
export const RootStateProvider: React.FC<React.PropsWithChildren<{}>> = ({children}) => {
// Finally pass new stores into the object below to send them to global state.
return (
<RootStateContext.Provider
value={{
triviaStore,
}}
>
{children}
</RootStateContext.Provider>
);
}
export const useGlobalState = () => React.useContext(RootStateContext);

在加载所有数据之前初始化存储在我看来是好的。您可以直接将加载状态添加到存储中。将async函数作为存储的方法放置是一个好主意。虽然我认为立即执行的async函数包装器没有效果,并且存储将在加载问题之前初始化。请看下面的例子:

@observable loading = true
constructor() {
// Same as with your wrapper, constructor cannot be made async.
this.loadQuestions()
}
@action
async loadQuestions() {
let questions: Question[] = await getQuestions()
// Newer versions of MobX will warn if runInAction missing after async call.
runInAction(() => {
this.questions = questions
this.lading = false
})
}

在我看来,不太好的部分是将MobX商店与React上下文混合在一起,我认为这是不必要的,因为你可以直接从任何地方导入商店。

尽管React将允许您获取一些数据,并且不会导致构造函数中的任何错误,但React开发人员不建议这样做,这不是一个好的实践。你应该从componentDidMount()中获取数据。

如果您的设计需要在加载页面后进行多次抓取,您可以尝试在componentDidUpdate()中完成,并更新您的初始状态。