Хичээлээр Үр дүнгийн компонент хичээлээр хийсэн компонентод динамик ажиллагааг хэрэгжүүлве. Өөрөөр хэлбэл сорилгын үр дүнг динамикаар үзүүлэх юм. Үүний тулд Quiz компонентод
const [results, setResults] = useState({})
сорилгын үр дүнгийн results төлвийг нэмэн өгье. results обьект үр дүнг {[асуултын_id]: хариултын_төлөв} хэлбэрээр агуулна. Өөрөөр хэлбэл хариултын төлөв талбарт хариулт зөв бол right буруу бол wrong утгыг агуулах юм.
Обьектод асуулт бүрээр элемент үүсэх ёстой учраас хэрэглэгчийн сонгосон хариултын боловсруулалтыг хийх onAnswerClickHandler аргад results төлвийг
const onAnswerClickHandler = (answerId) => {
if (quiz[activeQuestion].rightAnswerId === answerId) {
if (!results[quiz[activeQuestion].id]) {
setResults(prev => { return{...prev, [quiz[activeQuestion].id]: "right" }})
}
setAnswerState({ [answerId]: "right" })
const timeout = window.setTimeout(() => {
if (isQuizFinished()) {
setIsFinished(true)
} else {
setAnswerState(null)
setActiveQuestion(activeQuestion + 1)
}
window.clearTimeout(timeout);
}, 1000);
} else {
setResults(prev => { return{...prev, [quiz[activeQuestion].id]: "wrong" }})
setAnswerState({ [answerId]: "wrong" })
}
};
бүрдүүлэх логикийг нэмэн оруулъя. Асуултад буруу хариулсан бол setResults функцээр results обьектод тухайн асуултын id -тай wrong утгатай элементийг үүсгэнэ. Харин асуултад зөв хариулсан бол results обьектод тухайн асуултын id -тай элемент байхгүй буюу хэрэглэгч эхний сонголтоор зөв хариултыг өгсөн бол results обьектод тухайн асуултын id -тай right утгатай элементийг үүсгэнэ. Эсрэг тохиолдол буюу хэрэглэгч буруу хариултыг сонговол results обьектод тухайн асуултын id -тай элемент үүссэн бол өөрчлөлт хийгдэхгүй. setResults функц обьекттой ажиллах онцлогын талаар useState хук хичээлд дурдсанг эргэн харахыг зөвлөе.
Асуулт бүрээр results обьектод элемент үүсэх тул сорилго дуусахад түүнийг QuizResult компонентод
<div className={classes.QuizWrapper}>
<h3>Асуултуудад хариулна уу</h3>
{isFinished ? (
<QuizResult results={results} quiz={quiz}/>
) : (
<ActiveQuiz
...
/>
)}
</div>
дамжуулна. Үүний зэрэгцээ QuizResult компонент сорилгын асуултуудыг харуулах учраас quiz параметрээр асуултын массивийг бас дамжуулъя. Одоо сорилгын үр дүнг үзүүлэх QuizResult компонентийн кодийг
const QuizResult = (props) => {
return (
<div className={classes.QuizResult}>
<ul>
{props.quiz.map((quizItem, index) => {
const cls = [
"fa",
props.results[quizItem.id] === "wrong" ? "fa-times" : "fa-check",
classes[props.results[quizItem.id]],
];
return (
<li key={index}>
<strong>{index + 1}</strong>.
{quizItem.question}
<i className={cls.join(" ")} />
</li>
);
})}
</ul>
<p>12 асуултаас 4 -ыг зөв хариуллаа.</p>
<div>
<button>Дахин эхлэх</button>
</div>
</div>
)
}
гэж өөрчилье. QuizResult компонентод ирэх quiz параметрийг map функцээр итерац хийн асуултуудыг quizItem -д аван li тегээр харуулж байгаа. key={index} атрибут яагаад орж ирэх ёстойг Хариултын хувилбарууд хичээлээс мэднэ. map функц алхам бүрдээ quizItem -аар асуултыг өгөх тул түүний question талбарт асуулт байгаа гэдэг нь тодорхой. Хэрэглэгч асуултад зөв эсхүл буруу хариулсанг бид icon фонтоор үзүүлэхээр төлөвлөсөн тул icon фонтийн хэвжүүлэлтийг QuizResult компонентод ирсэн results параметрээр зохицуулна. Үүний тулд классийн cls массивийг үүсгээд түүнд классийн нэрүүдийг элемент байдлаар тодорхойлсон. icon фонт fa класстай байх ёстой. icon -ий нэр results параметрийн утгаас хамааран өөрчлөгдөх тул тухайн алхамын quizItem -ийн id талбарт тохирох results параметрийн утга буруу буюу wrong байвал fa-times эсрэг тохиолдолд fa-check фонтийн нэрийг өгнө. Үүнээс гадна cls массивийн гуравдах элементээр quizItem -ийн id талбарт тохирох results параметрийн утганд тохирох classes массивийн элементийг фонтийн өнгөөр өгнө. Эцэст нь i тегд cls массивийн join аргаар элементүүдийг хоосон зайгаар тусгаарлагдсан мөр болгон className атрибутад өгнө. Өөрлөлтийг хадгалаад сорилгыг ажлуулан үр дүнг харвал
гэж харагдана. Сорилгын асуултуудад хариулахдаа эхний асуултыг буруу харин хоёрдахь асуултыг эхний оролдлогоор зөв хариулсан үр дүн болохыг сануулъя. Та боломжит хувилбаруудаар шалган үзээрэй. Асуултын хариултын боловсруулалтыг динамик болголоо. Одоо хичнээн асуултаас хэдийг зөв хариулсанг QuizResult компонентод
const QuizResult = (props) => {
const rightCount = Object.keys(props.results).reduce((total, key) => {
if (props.results[key] === "right") {
total++;
}
return total;
}, 0);
return (
<div className={classes.QuizResult}>
...
<p>{props.quiz.length} асуултаас {rightCount} -ыг зөв хариуллаа.</p>
<div>
<button>Дахин эхлэх</button>
</div>
</div>
)
}
гэж динамик болгоё. QuizResult компонентод quiz параметрээр асуултууд ирж байгаа учраас нийт асуултын тоог props.quiz.length буюу quiz массивийн уртаар амархан тодорхойлно. Зөв хариултын тоог results параметрээс тооцохдоо rightCount хувьсагчийг үүсгэсэн. results обьект учраас Object классийн keys аргаар results обьектийг түлхүүр, утга хэлбэрийн массивт хөрвүүлээд массивийн reduce аргаар зөв хариултын тоог тооцсон. reduce аргад эхний параметрээр эргэн дуудалтын /callback/ функцийг хоёрдахь параметрээр үр дүнгийн буюу зөв хариултын эхний утгыг дамжуулсан. callback функцэд итераци бүрд зөв хариултыг тоолох total болон тухайн алхам дахь элементийн туүлхүүр key -г дамжуулна. Функцэд results -ийн key -д харгалзах элемент right утгатай бол total -ийг нэгээр нэмэгдүүлээд дараагийн алхамд хариултыг тоолох total -ийн эхний утга болгон буцаана. Ингэснээр хэрэглэгчийн зөв хариулсан асуултын тоог rightCount хувьсагчид олгоод түүнийг jsx -д оруулан өгнө.
Санамж: react өөрөө javascript сан тул бид javascript -ийн бүхий л боломжуудыг ашиглаж болно. Иймээс массивийн reduce арга гэлтгүй javascript -ийн хэлний боломжуудыг дэлгэрүүлэн судлахыг зөвлөе.
Өөрчлөлтийг хадгалаад сорилгын ажлуулбал
үр дүнг авна. Хэрэглэгч хичнээн асуултаас хэдийг зөв хариулсанг динамикаар үзүүллээ. QuizResult компонентийн Дахин эхлэх товчийг ажиллагаатай болгоё. Товч дээр дарахад дуудагдах функц Quiz компонентоос QuizResult компонентод пропсоор дамжин ирэх тул
<div>
<button onClick={props.onRetry}>Дахин эхлэх</button>
</div>
Дахин эхлэх товчинд onClick үйл явцын боловсруулагчийг тавиад props.onRetry утгыг өгье.
Санамж: react санг судалж эхлэж байгаа хүмүүст компонент хооронд параметр дамжуулж байгаа ажиллагаанууд ойлгомжгүй болоод төвөгтэй мэт санагдаж байж магадгүй. Олон параметрийг /пропс/ компонентуудаар дамжуулан шидэх нь зарим нэгэн талаар төвөгтэй нь үнэн хэдий ч эхлээд яг энэ аргачлалаар компонент хоорондын уялдан ажиллагааг ойлгох нь илүү байх болов уу. Сангийн ерөнхий ажиллагааны схемийг ойлгосоны дараа параметрүүдийг компонентуудаар дамжуулан шийдэхгүйгээр ашиглах context цаашлаад redux, mobx гэх мэтийн сангуудыг ашиглаж сурахыг зөвлөе.
onRetry функц QuizResult компонентод пропсоор ирнэ. Тэгвэл Quiz компонентоос QuizResult компонентийг дуудахдаа түүнд
<QuizResult
results={results}
quiz={quiz}
onRetry={retryHandler}
/>
onRetry атрибутаар retryHandler функцийг дамжуулъя. Quiz компонентод retryHandler функцийг
const retryHandler = () => {
setActiveQuestion(0)
setAnswerState(null)
setIsFinished(false)
setResults({})
}
гэж хэрэгжүүлэн өгье. Контекстийг алдахгүйн тулд retryHandler функцийг сумаар тодорхойлон өгнө. Сорилгын дахин эхлүүлэхийн тулд функцэд Quiz компонентийн шаардлагатай төлвүүдийг анхдагч утгатай болгох хэрэгтэй тул тохирох set функцуудаар сорилгын үед динамикаар утгууд авч байгаа төлвүүдийн анхдагч утгуудыг сэргээн олгосон. Өөрчлөлтийг хадгалаад сорилгыг дахин эхлүүлэн туршин үзээрэй.