ЁЯза рдзрдбрд╛ 05 тАФ State рдЖрдгрд┐ components: рд╕рддреНрдпрд╛рдЪрд╛ рдПрдХрдЪ рд╕реНрд░реЛрдд
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-javascript-events ┬╖ рдкреБрдвреЗ: lesson-06-accessibility
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ04, рдЖрдгрд┐ рддреА рдХрд▓реНрдкрдирд╛ рдЬреА automate рдХрд░рдгреНрдпрд╛рд╕рд╛рдареАрдЪ рдкреНрд░рддреНрдпреЗрдХ framework рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЖрд╣реЗ: state (рдореБрдЦреНрдп рдпрд╛рджреА), components (data рдкрд╛рд╕реВрди DOM рдмрдирд╡рдгрд╛рд░реА functions), рдЖрдгрд┐ рдПрдХрдЪ рдирд┐рдпрдо тАФ UI = render(state).
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╣рд╛ рдЖрд╣реЗ рд╕рд╛рдкрд│рд╛. рдлрд▓рдХрд╛рд╡рд░ рдкрд╛рдЪ рд╡рд┐рджреНрдпрд╛рд░реНрдереА рджрд┐рд╕рддрд╛рдд. рдПрдХрд╛ рдирд╡реАрди рд╡рд┐рджреНрдпрд╛рд░реНрдереНрдпрд╛рдЪреЗ рдирд╛рд╡ рдиреЛрдВрджрд╡рд▓реЗ рдЬрд╛рддреЗ, рдореНрд╣рдгреВрди рддреБрдореНрд╣реА рдПрдХ card рдЬреЛрдбрддрд╛. рдкрдг footer рдореНрд╣рдгрддреЗ "5 students on the board" тАФ рддреЗрд╣реА рдмрджрд▓рд╛. рдЖрдгрд┐ filter 3B рд╡рд░ рдЖрд╣реЗ, рдореНрд╣рдгреВрди рдХрджрд╛рдЪрд┐рдд рддреЗ card рджрд┐рд╕рд╛рдпрд▓рд╛рдЪ рдирдХреЛ. рдЖрдгрд┐ рд░рд┐рдХрд╛рдореНрдпрд╛ рдпрд╛рджреАрдЪрд╛ рд╕рдВрджреЗрд╢ рдЕрдЬреВрди рд▓рдкрд▓реЗрд▓рд╛рдЪ рдЖрд╣реЗтАж рдЖрддрд╛ рддреАрди рдард┐рдХрд╛рдгрд╛рдВрдирд╛ рд╕рддреНрдпрд╛рдЪрд╛ рдПрдХ-рдПрдХ рддреБрдХрдбрд╛ рдорд╛рд╣реАрдд рдЖрд╣реЗ, рдЖрдгрд┐ рдкреБрдврдЪреНрдпрд╛ рдЖрдард╡рдбреНрдпрд╛рдд рддреНрдпрд╛рдВрдЪреНрдпрд╛рдкреИрдХреА рдПрдХ рдЕрд╕рд╣рдордд рдЕрд╕реЗрд▓.
рдпрд╛рд╡рд░ рдЙрдкрд╛рдп рдореНрд╣рдгрдЬреЗ рдПрдХрд╛рдЪ object рдордзреНрдпреЗ рдареЗрд╡рд▓реЗрд▓реА рдореБрдЦреНрдп рдпрд╛рджреА ЁЯза:
const state = { students: [], filter: "", loading: true, error: null };
рдЗрддрд░ рдХрд╛рд╣реАрд╣реА рдХрд╛рд╣реАрдЪ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рдд рдирд╛рд╣реА. рдХрд╛рд╣реАрддрд░реА рдШрдбрд▓реЗ рдХреА рддреБрдореНрд╣реА state рдмрджрд▓рддрд╛
рдЖрдгрд┐ рдПрдХрдЪ function рдмреЛрд▓рд╡рддрд╛ тАФ render() тАФ рдЬреЗ рд╕рдзреНрдпрд╛рдЪреНрдпрд╛ state рд╡рд░реВрди рд╕рдВрдкреВрд░реНрдг рдлрд▓рдХ
рдХрд╛рдврддреЗ: cards, status рдУрд│, рд╕рдВрдЦреНрдпрд╛. рдлрд▓рдХ рдХрдзреАрдЪ рд╕реНрд╡рддрдГрд╢реА рдЕрд╕рд╣рдордд
рд╣реЛрдК рд╢рдХрдд рдирд╛рд╣реА, рдХрд╛рд░рдг рд╕рддреНрдпрд╛рдЪрд╛ рд╕реНрд░реЛрдд рдПрдХрдЪ рдЖрд╣реЗ.
рдЖрдгрд┐ рдХрд╛рдврдгреНрдпрд╛рдЪреЗ рдХрд╛рдо components ЁЯзй рдордзреНрдпреЗ рд╡рд┐рднрд╛рдЧрд▓реЗрд▓реЗ рдЖрд╣реЗ тАФ рдЫреЛрдЯреА functions рдЬреА
data рдЪрд╛ рдПрдХ рддреБрдХрдбрд╛ DOM рдЪреНрдпрд╛ рдПрдХрд╛ рддреБрдХрдбреНрдпрд╛рдд рдмрджрд▓рддрд╛рдд: StudentCard(s) рдПрдХ рд╡рд┐рджреНрдпрд╛рд░реНрдереА рдШреЗрддреЗ рдЖрдгрд┐
рдПрдХ card рдкрд░рдд рджреЗрддреЗ. рддреЗрдЪ input, рддреЗрдЪ output, рдХреЛрдгрддреЗрд╣реА рдЖрд╢реНрдЪрд░реНрдп рдирд╛рд╣реА.
UI = render(state). рд╣реЗ рдПрдХрд╛ sticky note рд╡рд░ рд▓рд┐рд╣реВрди рдареЗрд╡рд╛. Lesson 07 рдордзрд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ framework рдиреЗрдордХреЗ рд╣реЗрдЪ рдХрд░рдгреНрдпрд╛рдЪрд╛ рдПрдХ рд╣реБрд╢рд╛рд░, рдЬрд▓рдж рдорд╛рд░реНрдЧ рдЖрд╣реЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
ev["ЁЯСЖ event"] --> st["ЁЯза state = {students, filter, loading, error}<br/>the ONLY source of truth"]
st --> r["ЁЯФБ render(state)"]
r --> c1["ЁЯзй StudentCard(s) тЖТ card"]
r --> c2["ЁЯзй status line"]
r --> c3["ЁЯзй count in the footer"]
c1 & c2 & c3 --> dom["ЁЯУД the DOM"]
note["never edit the DOM outside render()"]
тЭУ рдХрд╛рдп
- State: рдлрд▓рдХрд╛рдиреЗ рдЖрддреНрддрд╛ рдХрд╛рдп рджрд╛рдЦрд╡рд╛рдпрд▓рд╛ рд╣рд╡реЗ рддреЗ рд╕рд╛рдВрдЧрдгрд╛рд░рд╛ рд╕рд╛рдзрд╛ data тАФ
server data (
students), UI state (filter), request state (loading,error). рдмрд╛рдХреА рд╕рдЧрд│реЗ (filter рдХреЗрд▓реЗрд▓реА list, рд╕рдВрдЦреНрдпрд╛)render()рдЪреНрдпрд╛ рдЖрдд рдХрд╛рдврд╛. - Components:
function StudentCard(student) тЖТ Element. рд╢реБрджреНрдз: рдХреЛрдгрддреЗрд╣реА fetching рдирд╛рд╣реА, global state рдирд╛рд╣реА, side effects рдирд╛рд╣реАрдд. Test рдХрд░рд╛рдпрд▓рд╛ рд╕реЛрдкреЗ (lesson 10). - рдирд┐рдпрдо: handlers state рдмрджрд▓рддрд╛рдд, рдордЧ
render()рдмреЛрд▓рд╡рддрд╛рдд. рдЗрддрд░ рдХрд╛рд╣реАрд╣реА DOM рдордзреНрдпреЗ рд▓рд┐рд╣реАрдд рдирд╛рд╣реА. рдЖрдкрд▓реЗrender()рд╕рдВрдкреВрд░реНрдг list рдПрдХрджрдо рдмрджрд▓рдгреНрдпрд╛рд╕рд╛рдареАreplaceChildren(...)рд╡рд╛рдкрд░рддреЗ. - рдХрд╛рдврд▓реЗрд▓реА state рдореНрд╣рдгрдЬреЗ state рдирд╡реНрд╣реЗ:
filteredStudentsрд╕рд╛рдард╡реВ рдирдХрд╛ тАФ рддреЗ рдЧрдгрдирд╛ рдХрд░реВрди рдХрд╛рдврд╛. рдПрдХрд╛рдЪ рд╕рддреНрдпрд╛рдЪреНрдпрд╛ рджреЛрди рдкреНрд░рддреА рдиреЗрд╣рдореА рдПрдХрдореЗрдХрд╛рдВрдкрд╛рд╕реВрди рджреВрд░ рдЬрд╛рддрд╛рдд. - Performance: рдЫреЛрдЯреА list рдкреБрдиреНрд╣рд╛ рдмрд╛рдВрдзрдгреЗ рд╕реНрд╡рд╕реНрдд рдЕрд╕рддреЗ. рддрд╕реЗ рдирд╕реЗрд▓, рддрд░ рддреБрдореНрд╣реА рдПрдХрддрд░ key рджреЗрдКрди diff рдХрд░рддрд╛ (React рд╣реЗрдЪ рдХрд░рддреЛ) рдХрд┐рдВрд╡рд╛ рдиреЗрдордХрд╛ рднрд╛рдЧрдЪ рдмрджрд▓рддрд╛ тАФ рдкрдг рдлрдХреНрдд рдореЛрдЬрдорд╛рдк рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ (lesson 09).
- рдереЛрдбреА UI state (theme) рдЯрд┐рдХрд╡реВрди рдареЗрд╡рд╛рдпрдЪреА рдЕрд╕реЗрд▓ рддрд░
localStorageрдЪрд╛рд▓рддреЗ тАФtry/catchрдордзреНрдпреЗ рдЧреБрдВрдбрд╛рд│реВрди, рдХрд╛рд░рдг private browsing рдордзреНрдпреЗ рддреЗ throw рдХрд░реВ рд╢рдХрддреЗ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "рдХрд╛рдЙрдВрдЯрд░ 5 рдореНрд╣рдгрд╛рд▓рд╛ рдкрдг рдорд▓рд╛ 6 рджрд┐рд╕рддрд╛рдд" рд╣рд╛ UI bugs рдЪрд╛ рд╕рд░реНрд╡рд╛рдд рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдЖрд╣реЗ, рдЖрдгрд┐ рддреЛ рдПрдХрдЪ рдЧреЛрд╖реНрдЯ рдПрдХрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдард┐рдХрд╛рдгреА рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд▓реНрдпрд╛рдореБрд│реЗ рд╣реЛрддреЛ. рд╣рд╛ рдПрдХрдЪ рдирд┐рдпрдо рддреЛ рд╕рдВрдкреВрд░реНрдг рдкреНрд░рдХрд╛рд░рдЪ рдХрд╛рдвреВрди рдЯрд╛рдХрддреЛ тАФ рдЖрдгрд┐ рдкреБрдврдЪреНрдпрд╛ рдзрдбреНрдпрд╛рдд React, Vue рдХрд┐рдВрд╡рд╛ Svelte рдордзреНрдпреЗ рддреБрдореНрд╣реА рдиреЗрдордХреЗ рд╣реЗрдЪ рдорд╛рдирд╕рд┐рдХ рдЪрд┐рддреНрд░ рдШреЗрдКрди рдЬрд╛рд▓.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
ui/app.js рдЪреЗ рднрд╛рдЧ 1 рдЖрдгрд┐ 2: рд╕рд░реНрд╡рд╛рдд рд╡рд░ state,
рддреНрдпрд╛рдЦрд╛рд▓реА StudentCard(s) рдЖрдгрд┐ render(). рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛ рдХреА рдХреЛрдгрддреА cards рдХрд╛рдврд╛рдпрдЪреА рд╣реЗ
рдард░рд╡рдгреНрдпрд╛рд╕рд╛рдареА render() state.filter рд╡рд╛рдЪрддреЗ рдЖрдгрд┐ status рдордЬрдХреВрд░ рд╡
footer рдордзрд▓реА рд╕рдВрдЦреНрдпрд╛ рд▓рд┐рд╣рд┐рддреЗ тАФ рддреАрди рджреГрд╢реНрдпреЗ, рдПрдХрдЪ рд╕рддреНрдп.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 ui/mock_api.py
# 1) prove the rule holds: enrol a student while the filter is on 3A тАФ the count updates, the card appears only if it matches
# 2) break it on purpose: in the submit handler, replace `state.students.push(s); render();`
# with `document.querySelector('#student-list').appendChild(StudentCard(s));`
# then change the filter тАФ your student vanishes, and the footer count is wrong. That is the bug this lesson kills.
# 3) put it back, then add real state: a `sort` field ('name' | 'grade'), a <select> that sets it, and one line in render()
# 4) in the Console: state (it is inside the IIFE тАФ so expose it temporarily with window.state = state to inspect)
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
рдирд┐рдпрдо рдкрд╛рд│рд▓реНрдпрд╛рд╡рд░: state рдордзрд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ рдмрджрд▓ рдПрдХрд╕рдВрдз рдлрд▓рдХ рдкреБрдиреНрд╣рд╛ рд░рдВрдЧрд╡рддреЛ. рд╣рд╛рддрд╛рдиреЗ
рдмрджрд▓ рдХреЗрд▓реНрдпрд╛рд╡рд░: card DOM рдордзреНрдпреЗ рдЕрд╕рддреЗ рдкрдг state рдордзреНрдпреЗ рдирд╕рддреЗ, рдореНрд╣рдгреВрди рдкреБрдврдЪреЗ render()
рддреЗ рдкреБрд╕реВрди рдЯрд╛рдХрддреЗ рдЖрдгрд┐ рд╕рдВрдЦреНрдпрд╛ рдХрдзреАрдЪ рдмрд░реЛрдмрд░ рдирд╡реНрд╣рддреА. рддреБрдордЪреНрдпрд╛ рдирд╡реАрди sort control рд▓рд╛
render() рдордзреНрдпреЗ рдиреЗрдордХреА рдПрдХ рдУрд│ рд▓рд╛рдЧрддреЗ, рдЖрдгрд┐ рдЗрддрд░ рдХреЛрдгрддрд╛рд╣реА рдмрджрд▓ рд▓рд╛рдЧрдд рдирд╛рд╣реА.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдПрдХрд╛ object рдиреЗ рд╕рддреНрдп рдзрд░реВрди рдареЗрд╡рд▓реЗ, рдПрдХрд╛ function рдиреЗ рддреЗ рдХрд╛рдврд▓реЗ, рдЖрдгрд┐ рдирд╡реАрди feature рдЬреЛрдбрдгреЗ рдореНрд╣рдгрдЬреЗ
state рдЖрдгрд┐ render() рдмрджрд▓рдгреЗ тАФ рд╕рдВрдЦреНрдпрд╛ рджрд╛рдЦрд╡рдгрд╛рд░реА рдкреНрд░рддреНрдпреЗрдХ рдЬрд╛рдЧрд╛ рд╢реЛрдзрдд рдмрд╕рдгреЗ
рдирд╡реНрд╣реЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
render()рдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░ DOM рдмрджрд▓рдгреЗ (рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдореБрджреНрджрд╛рдо рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓рд╛ bug)- рдХрд╛рдврд▓реЗрд▓рд╛ data (
filteredStudents,count) state рдордзреНрдпреЗ рд╕рд╛рдард╡рдгреЗ - рдкреНрд░рддреНрдпреЗрдХ keystroke рд▓рд╛ рдЬрдб рдЧреЛрд╖реНрдЯреА рдкреБрдиреНрд╣рд╛ рдмрд╛рдВрдзрдгрд╛рд░реЗ рдПрдХрдЪ рдкреНрд░рдЪрдВрдб
render()тАФ components рд╡реЗрдЧрд│реЗ рдХрд░рд╛, рдХрд┐рдВрд╡рд╛ input debounce рдХрд░рд╛ - рдЕрдиреЗрдХ files рдордзреНрдпреЗ рд╡рд┐рдЦреБрд░рд▓реЗрд▓реНрдпрд╛ globals рдордзреНрдпреЗ state рдареЗрд╡рдгреЗ
- рд╣рд╛ рдирд┐рдпрдо рдХрд╛ рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЖрд╣реЗ рддреЗ рдЕрдиреБрднрд╡рдгреНрдпрд╛рдЖрдзреАрдЪ framework рдХрдбреЗ рдзрд╛рд╡ рдШреЗрдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: React рдЪреЗ
useState, Vue рдЪреЗrefрдЖрдгрд┐ Svelte рдЪреЗ$stateрдореНрд╣рдгрдЬреЗ diffing engine рдЬреЛрдбрд▓реЗрд▓рд╛ рд╣рд╛рдЪ рдзрдбрд╛. рдЬреНрдпрд╛ teams рдирд╛ рд╣реЗ рд╕рдордЬрддреЗ рддреНрдпрд╛ frameworks debug рдХрд░рддрд╛рдд; рдЬреНрдпрд╛рдВрдирд╛ рд╕рдордЬрдд рдирд╛рд╣реА рддреНрдпрд╛ frameworks рд╢реА рднрд╛рдВрдбрдд рдмрд╕рддрд╛рдд.
тПня╕П рдкреБрдвреЗ
рдлрд▓рдХ рдПрдХрд╕рдВрдз рдЖрд╣реЗ тАФ рдкрдг рдкреНрд░рддреНрдпреЗрдХрдЬрдг рддреЛ рд╡рд╛рдкрд░реВ рд╢рдХрддреЛ рдХрд╛? Accessibility: keyboard, labels, contrast, focus рдЖрдгрд┐ рдШреЛрд╖рдгрд╛.
git checkout lesson-06-accessibility