#javascript #reactjs #mongoose #mern
Вопрос:
Я создаю приложение MERN, которое выполняет операции CRUD с базой данных вопросов викторины.
Интерфейс не будет иметь функций для записи ответов на эти вопросы, он предназначен исключительно для просмотра, редактирования и удаления вопросов.
Вопросы бывают трех типов — один ответ, несколько ответов (два или более «варианта ответа» являются правильными) и множественный выбор (один из нескольких «вариантов ответа» является правильным).
Схема вопроса выглядит так:
const optionSchema = new mongoose.Schema({
optionText: { type: String, required: true },
isAnswer: { type: Boolean, required: true },
});
const locationSchema = new mongoose.Schema({
locationName: { type: String, required: true },
});
const questionSchema = mongoose.Schema(
{
content: {
type: String,
required: true,
maxLength: 1000,
},
answerOptions: [optionSchema],
author: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
locations: [locationSchema],
category: {
type: String,
required: true,
},
questionType: {
type: String,
},
isFlagged: {
type: Boolean,
default: false,
},
flagReason: {
type: String,
},
isPublic: {
type: Boolean,
default: true,
},
checkDate: {
type: Date,
},
qualityVoteTotal: {
type: Number,
},
difficultyVoteTotal: {
type: Number,
},
isDeprecated: {
type: Boolean,
},
},
{
timestamps: true,
}
);
const Question = mongoose.model("Question", questionSchema);
У меня есть экран интерфейса, на котором отображается список вопросов из базы данных. Они отправляются из магазина redux с использованием:
function QuestionBrowser({ history }) {
const dispatch = useDispatch();
const questionList = useSelector((state) => state.questionList);
const { loading, error, questions } = questionList;
И я пытаюсь отобразить каждый вопрос с его ответами и некоторой другой информацией в аккордеоне начальной загрузки:
return (
<MainScreen title={`Have a browse ${userInfo amp;amp; userInfo.name}..`}>
<Link to="/createquestion">
<Button style={{ marginLeft: 10, marginBottom: 6 }} size="lg">
Create new question
</Button>
</Link>
{error amp;amp; <ErrorMessage variant="danger">{error}</ErrorMessage>}
{/* {errorDelete amp;amp; (
<ErrorMessage variant="danger">{errorDelete}</ErrorMessage>
)} */}
{loading amp;amp; <Loading />}
{/* {loadingDelete amp;amp; <Loading />} */}
{questions amp;amp;
questions.reverse().map((question) => (
<Accordion>
<Card style={{ margin: 10 }} key={question._id}>
<Card.Header style={{ display: "flex" }}>
<span
// onClick={() => ModelShow(question)}
style={{
color: "black",
textDecoration: "none",
flex: 1,
cursor: "pointer",
alignSelf: "center",
fontSize: 18,
}}
>
<Accordion.Toggle as={Card.Text} variant="link" eventKey="0">
{question.content}
</Accordion.Toggle>
</span>
<div>
<Button href={`/question/${question._id}`}>Edit</Button>
<Button
variant="danger"
className="mx-2"
// onClick={() => deleteHandler(question._id)}
>
Delete
</Button>
</div>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<h4>
Category - {question.category}
</h4>
<blockquote className="blockquote mb-0">
{/* Hard coding displays the answer options... */}
{/* {question.answerOptions[0].optionText}
{question.answerOptions[1].optionText}
{question.answerOptions[2].optionText} */}
<footer className="blockquote-footer">
Created on{" "}
<cite title="Source Title">
{question.createdAt.substring(0, 10)}
</cite>
</footer>
</blockquote>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
))}
</MainScreen>
);
An example question, returned from the database currently looks like:
{
"_id": "61464a067b9b883824daeeeb",
"content": "Where was E.T. trying to phone in a class 1980s movie?",
"answerOptions": [
{
"optionText": "The International Space Station",
"isAnswer": false,
"_id": "6146530f7b22de77fb129e4f"
},
{
"optionText": "Home",
"isAnswer": true,
"_id": "6146530f7b22de77fb129e50"
},
{
"optionText": "The Chinese takeaway",
"isAnswer": false,
"_id": "6146530f7b22de77fb129e51"
}
],
"author": "614647baff6a022c04218203",
"locations": [],
"category": "Entertainment",
"questionType": "Multiple Choice",
"isFlagged": false,
"flagReason": "",
"isPublic": true,
"checkDate": null,
"qualityVoteTotal": 0,
"difficultyVoteTotal": 0,
"isDeprecated": false,
"createdAt": "2021-09-18T20:20:22.298Z",
"updatedAt": "2021-09-18T20:58:55.075Z",
"__v": 1
}
I’m able to output the answer options by hardcoding the following into my QuestionBrowser’s return, by using the following:
<blockquote className="blockquote mb-0">
{question.answerOptions[0].optionText}
{question.answerOptions[1].optionText}
{question.answerOptions[2].optionText}
But given the number of answerOptions in each question document can vary (only one answerOption for a single answer question, up to six options for multiple answer and multiple choice questions), this isn’t practical.
For each question I’m trying to find a way to:
- Display the question.content in the accordion toggle (this is working at the moment)
- Iterate through the answerOptions array, and for each option, output the text in the accordion body, making the text bold (for example) if the isAnswer property is true.