javascript - การเรียกฟังก์ชัน async ที่กำลังดึงข้อมูลเริ่มต้นในตัวสร้างของคลาส JS ทำได้หรือไม่?
ฉันกำลังสร้างตัวอย่างแอปด้วย Mobx และ Mobx React Lite เพื่อเรียนรู้วิธีการใช้ไลบรารีการจัดการสถานะนี้ แอปต้องโหลดคำถามเมื่อผู้ใช้เข้าชมหน้านี้ สามารถเรียกโหลดข้อมูลเริ่มต้นในคอนสตรัคเตอร์แบบนี้ได้ไหม? มันอาจทำให้เกิดบั๊กได้หรือไม่?
ความกังวลของฉันคือมันอาจจะเกิดขึ้นอีกครั้ง แต่ฉันไม่แน่ใจว่านั่นอาจเป็นความกังวลเดียวที่ฉันควรมีหรือไม่
คุณจะแนะนำรูปแบบอื่นอะไรถ้านี่เสี่ยง?
ไอเดียทางเลือกของฉันคือการเอามันออกจากบริบทเมื่อพวกเขาคลิกปุ่ม "เริ่มทำแบบทดสอบ" และมีหน้าจอโหลดขณะดึงข้อมูลมา วิธีนี้น่าจะเป็นวิธีที่ควรเกิดขึ้นที่สุด แต่ฉันก็แค่สงสัยว่าที่ฉันทำไปนั้นก็โอเคหรือไม่เช่นกัน
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);
คำตอบ #1
การเริ่มต้นร้านค้าก่อนที่ข้อมูลทั้งหมดจะถูกโหลดเป็นเรื่องที่ดีในความคิดเห็นของฉัน คุณสามารถเพิ่มสถานะการโหลดโดยตรงไปที่ร้านค้า การวางฟังก์ชันแบบอะซิงค์เป็นเมธอดในร้านค้าเป็นความคิดที่ดี แม้ว่าฉันคิดว่าฟังก์ชันอะซิงค์ที่ถูกเรียกใช้งานทันทีไม่มีผลและร้านค้าจะถูกเริ่มต้นก่อนที่คำถามจะถูกโหลด ดูตัวอย่างนี้:
@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 store กับ React Context ซึ่งฉันคิดว่าไม่จำเป็นเพราะคุณสามารถนำเข้า store โดยตรงจากที่ไหนก็ได้อยู่แล้ว
คำตอบ #2
แม้ว่า React จะอนุญาตให้คุณดึงข้อมูลบางอย่างและจะไม่ทำให้เกิดข้อบกพร่องใด ๆ ใน constructor แต่ก็ไม่แนะนำโดยนักพัฒนาของ React และไม่ใช่แนวทางที่ดี คุณควรดึงข้อมูลของคุณใน componentDidMount() แทน
ถ้าการออกแบบของคุณต้องการการดึงข้อมูลหลายครั้งหลังจากที่คุณโหลดหน้าเว็บ คุณสามารถลองทำใน componentDidUpdate() และอัปเดตสภาวะเริ่มต้นของคุณ
