【发布时间】:2021-10-14 23:25:55
【问题描述】:
所以我正在尝试调试为什么我的问题数组没有正确填充到我的 mobx-state-tree questions-store 中。 getQuestions 操作中的 yield 语句之后没有任何内容运行。
// question-store.ts
import { Instance, SnapshotOut, types, flow } from "mobx-state-tree"
import { Question, QuestionModel, QuestionSnapshot } from "../question/question";
import { withEnvironment } from '../';
import { GetQuestionsResult } from "../../services/api";
export const QuestionStoreModel = types
.model("QuestionStore")
.props({
questions: types.optional(types.array(QuestionModel), [])
})
.extend(withEnvironment)
.views((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars
.actions((self) => ({
saveQuestions: (questionSnapshots: QuestionSnapshot[]) => {
console.tron.log("SAVE QUESTIONS");
console.tron.log({ questionSnapshots });
const questionModels: Question[] = questionSnapshots.map(c => QuestionModel.create(c));
self.questions.replace(questionModels); // Replace the existing data with the new data
}
}))
.actions((self) => ({
getQuestions: flow(function*() {
console.tron.log("GET QUESTIONS");
const result: GetQuestionsResult = yield self.environment.api.getQuestions(); // Nothing after this yield statement runs
console.tron.log("AFTER GET QUESTIONS");
if (result.kind === "ok") {
self.saveQuestions(result.questions);
} else {
__DEV__ && console.tron.log(result.kind);
}
})
}))
type QuestionStoreType = Instance<typeof QuestionStoreModel>
export interface QuestionStore extends QuestionStoreType {}
type QuestionStoreSnapshotType = SnapshotOut<typeof QuestionStoreModel>
export interface QuestionStoreSnapshot extends QuestionStoreSnapshotType {}
export const createQuestionStoreDefaultModel = () => types.optional(QuestionStoreModel, {})
这是 api 的 getQuestions
import { ApisauceInstance, create, ApiResponse } from "apisauce"
import { getGeneralApiProblem } from "./api-problem"
import { ApiConfig, DEFAULT_API_CONFIG } from "./api-config"
import * as Types from "./api.types"
import uuid from 'react-native-uuid';
import { QuestionSnapshot, Question } from "../../models";
const API_PAGE_SIZE = 5;
const convertQuestion = (raw: any): QuestionSnapshot => {
const id = uuid.v4().toString();
return {
id: id,
category: raw.category,
type: raw.type,
difficulty: raw.difficulty,
question: raw.question,
correctAnswer: raw.correct_answer,
incorrectAnswers: raw.incorrect_answers,
}
}
/**
* Manages all requests to the API.
*/
export class Api {
/**
* The underlying apisauce instance which performs the requests.
*/
apisauce: ApisauceInstance
/**
* Configurable options.
*/
config: ApiConfig
/**
* Creates the api.
*
* @param config The configuration to use.
*/
constructor(config: ApiConfig = DEFAULT_API_CONFIG) {
this.config = config
}
/**
* Sets up the API. This will be called during the bootup
* sequence and will happen before the first React component
* is mounted.
*
* Be as quick as possible in here.
*/
setup() {
// construct the apisauce instance
this.apisauce = create({
baseURL: this.config.url,
timeout: this.config.timeout,
headers: {
Accept: "application/json",
},
})
}
async getQuestions(): Promise<Types.GetQuestionsResult> {
// make the api call
const response: ApiResponse<any> = await this.apisauce.get("", { amount: API_PAGE_SIZE })
console.tron.log({response});
// the typical ways to die when calling an api
if (!response.ok) {
const problem = getGeneralApiProblem(response);
if (problem) return problem;
}
console.tron.log('AFTER OK CHECK')
// transform the data into the format we are expecting
try {
const rawQuestion = response.data.results;
console.tron.log({rawQuestion});
const convertedQuestions: QuestionSnapshot[] = rawQuestion.map(convertQuestion);
console.tron.log({convertedQuestions});
return { kind: "ok", questions: convertedQuestions };
} catch (e) {
__DEV__ && console.tron.log(e.message);
return { kind: 'bad-data' }
}
}
async getUsers(): Promise<Types.GetUsersResult> {
// make the api call
const response: ApiResponse<any> = await this.apisauce.get(`/users`)
// the typical ways to die when calling an api
if (!response.ok) {
const problem = getGeneralApiProblem(response)
if (problem) return problem
}
const convertUser = (raw) => {
return {
id: raw.id,
name: raw.name,
}
}
// transform the data into the format we are expecting
try {
const rawUsers = response.data
const resultUsers: Types.User[] = rawUsers.map(convertUser)
return { kind: "ok", users: resultUsers }
} catch {
return { kind: "bad-data" }
}
}
/**
* Gets a single user by ID
*/
async getUser(id: string): Promise<Types.GetUserResult> {
// make the api call
const response: ApiResponse<any> = await this.apisauce.get(`/users/${id}`)
// the typical ways to die when calling an api
if (!response.ok) {
const problem = getGeneralApiProblem(response)
if (problem) return problem
}
// transform the data into the format we are expecting
try {
const resultUser: Types.User = {
id: response.data.id,
name: response.data.name,
}
return { kind: "ok", user: resultUser }
} catch {
return { kind: "bad-data" }
}
}
}
问题模型:
import { Instance, SnapshotOut, types } from "mobx-state-tree"
import { shuffle } from "lodash";
export const QuestionModel = types
.model("Question")
.props({
id: types.identifier,
category: types.maybe(types.string),
type: types.enumeration(['multiple', 'boolean']),
difficulty: types.enumeration(['easy', 'medium', 'hard']),
question: types.maybe(types.string),
correctAnswer: types.maybe(types.string),
incorrectAnswers: types.optional(types.array(types.string), []),
guess: types.maybe(types.string)
})
.views((self) => ({
get allAnswers() {
return shuffle(self.incorrectAnswers.concat([self.correctAnswer]))
},
get isCorrect() {
return self.guess === self.correctAnswer;
}
}))
.actions((self) => ({
setGuess(guess: string) {
self.guess = guess;
}
}))
type QuestionType = Instance<typeof QuestionModel>
export interface Question extends QuestionType {}
type QuestionSnapshotType = SnapshotOut<typeof QuestionModel>
export interface QuestionSnapshot extends QuestionSnapshotType {}
export const createQuestionDefaultModel = () => types.optional(QuestionModel, {})
从日志中可以看出,api 调用成功,convertedQuestions 正确记录,但之后没有任何记录。也许我误解了生成器函数的工作原理,但它不应该在产生函数返回值后恢复吗?
任何见解都将不胜感激。
【问题讨论】:
标签: typescript react-native expo mobx-state-tree apisauce