Amaliy loyiha — Class komponentda Todo

DarslarWeb dasturlash

Amaliy loyiha — Class komponentda Todo

Class komponentlar, state, setState, metodlar va lifecycle — hammasi birgalikda. To'liq Todo ilova.

70 daqiqa
React — Dars 9

Todo App — Class Component

Class, state, setState, propsni bolalarga uzatish — React'ning old uslubi bilan real loyiha quramiz.

classstatesetStateprops

Bosqichlar

6 ta mavzu
  1. 01Loyiha strukturasi
  2. 02App class — state va metodlar
  3. 03TodoForm — forma
  4. 04TodoList + TodoItem
  5. 05Filtrlash
  6. 06localStorage va lifecycle

1. Loyiha strukturasi

1src/
2├── components/
3│ ├── TodoForm.jsx // yangi vazifa qo'shish
4│ ├── TodoList.jsx // ro'yxat
5│ ├── TodoItem.jsx // bitta vazifa
6│ └── Filter.jsx // filtr tugmalari
7├── App.jsx // asosiy class
8├── App.css
9└── main.jsx

2. App class — state va metodlar

src/App.jsx
1import React, { Component } from "react";
2import TodoForm from "./components/TodoForm";
3import TodoList from "./components/TodoList";
4import Filter from "./components/Filter";
5import "./App.css";
6
7class App extends Component {
8 state = {
9 vazifalar: [],
10 filtr: "all", // all | active | done
11 };
12
13 // Lifecycle — sahifa ochilganda localStorage'dan yuklash
14 componentDidMount() {
15 const saved = localStorage.getItem("vazifalar");
16 if (saved) {
17 this.setState({ vazifalar: JSON.parse(saved) });
18 }
19 }
20
21 // Har o'zgarganda saqlash
22 componentDidUpdate(prevProps, prevState) {
23 if (prevState.vazifalar !== this.state.vazifalar) {
24 localStorage.setItem(
25 "vazifalar",
26 JSON.stringify(this.state.vazifalar)
27 );
28 }
29 }
30
31 qoshish = (matn) => {
32 const yangi = {
33 id: Date.now(),
34 matn,
35 bajarildi: false,
36 };
37 this.setState(oldin => ({
38 vazifalar: [...oldin.vazifalar, yangi],
39 }));
40 };
41
42 ochir = (id) => {
43 this.setState(oldin => ({
44 vazifalar: oldin.vazifalar.filter(v => v.id !== id),
45 }));
46 };
47
48 toggle = (id) => {
49 this.setState(oldin => ({
50 vazifalar: oldin.vazifalar.map(v =>
51 v.id === id ? { ...v, bajarildi: !v.bajarildi } : v
52 ),
53 }));
54 };
55
56 filtrOzgartir = (yangiFiltr) => {
57 this.setState({ filtr: yangiFiltr });
58 };
59
60 render() {
61 const { vazifalar, filtr } = this.state;
62
63 // Filtrlash
64 const korinadigan = vazifalar.filter(v => {
65 if (filtr === "active") return !v.bajarildi;
66 if (filtr === "done") return v.bajarildi;
67 return true;
68 });
69
70 const faolSoni = vazifalar.filter(v => !v.bajarildi).length;
71
72 return (
73 <div className="app">
74 <h1>Vazifalarim</h1>
75
76 <TodoForm qoshish={this.qoshish} />
77
78 <Filter
79 joriy={filtr}
80 ozgartir={this.filtrOzgartir}
81 />
82
83 <TodoList
84 vazifalar={korinadigan}
85 ochir={this.ochir}
86 toggle={this.toggle}
87 />
88
89 <p className="stats">
90 {faolSoni} ta bajarilmagan, jami {vazifalar.length}
91 </p>
92 </div>
93 );
94 }
95}
96
97export default App;

3. TodoForm — forma

src/components/TodoForm.jsx
1import React, { Component } from "react";
2
3class TodoForm extends Component {
4 state = { matn: "" };
5
6 onChange = (e) => {
7 this.setState({ matn: e.target.value });
8 };
9
10 onSubmit = (e) => {
11 e.preventDefault();
12 const matn = this.state.matn.trim();
13 if (!matn) return;
14
15 this.props.qoshish(matn);
16 this.setState({ matn: "" });
17 };
18
19 render() {
20 return (
21 <form onSubmit={this.onSubmit}>
22 <input
23 type="text"
24 value={this.state.matn}
25 onChange={this.onChange}
26 placeholder="Yangi vazifa..."
27 />
28 <button type="submit">Qo'sh</button>
29 </form>
30 );
31 }
32}
33
34export default TodoForm;

4. TodoList + TodoItem

src/components/TodoList.jsx
1import React, { Component } from "react";
2import TodoItem from "./TodoItem";
3
4class TodoList extends Component {
5 render() {
6 const { vazifalar, ochir, toggle } = this.props;
7
8 if (vazifalar.length === 0) {
9 return <p className="empty">Hali vazifa yo'q</p>;
10 }
11
12 return (
13 <ul>
14 {vazifalar.map(v => (
15 <TodoItem
16 key={v.id}
17 vazifa={v}
18 ochir={ochir}
19 toggle={toggle}
20 />
21 ))}
22 </ul>
23 );
24 }
25}
26
27export default TodoList;
src/components/TodoItem.jsx
1import React, { Component } from "react";
2
3class TodoItem extends Component {
4 render() {
5 const { vazifa, ochir, toggle } = this.props;
6
7 return (
8 <li className={vazifa.bajarildi ? "done" : ""}>
9 <input
10 type="checkbox"
11 checked={vazifa.bajarildi}
12 onChange={() => toggle(vazifa.id)}
13 />
14 <span>{vazifa.matn}</span>
15 <button
16 className="del"
17 onClick={() => ochir(vazifa.id)}
18 >
19 ×
20 </button>
21 </li>
22 );
23 }
24}
25
26export default TodoItem;

5. Filtrlash

src/components/Filter.jsx
1import React, { Component } from "react";
2
3class Filter extends Component {
4 render() {
5 const { joriy, ozgartir } = this.props;
6 const turlari = [
7 { id: "all", nom: "Hammasi" },
8 { id: "active", nom: "Faol" },
9 { id: "done", nom: "Bajarilgan" },
10 ];
11
12 return (
13 <div className="filter">
14 {turlari.map(t => (
15 <button
16 key={t.id}
17 className={joriy === t.id ? "active" : ""}
18 onClick={() => ozgartir(t.id)}
19 >
20 {t.nom}
21 </button>
22 ))}
23 </div>
24 );
25 }
26}
27
28export default Filter;

6. localStorage va lifecycle

App.jsx'dagi componentDidMount — birinchi chizilganda localStorage'dan yuklaydi. componentDidUpdate — vazifalar o'zgarganda saqlaydi. Bu «persistent» ma'lumot effekti beradi.

src/App.css
1* { box-sizing: border-box; margin: 0; padding: 0; font-family: system-ui, sans-serif; }
2body { background: #0f172a; color: white; min-height: 100vh; padding: 40px 16px; }
3.app { max-width: 540px; margin: 0 auto; background: #1e293b; padding: 28px; border-radius: 16px; }
4h1 { margin-bottom: 18px; }
5
6form { display: flex; gap: 8px; margin-bottom: 16px; }
7form input { flex: 1; padding: 10px 14px; border-radius: 8px; border: 1.5px solid #334155; background: #0f172a; color: white; font-size: 15px; }
8form button { padding: 10px 18px; border: none; border-radius: 8px; background: #fbbf24; color: #0f172a; font-weight: 700; cursor: pointer; }
9
10.filter { display: flex; gap: 6px; margin-bottom: 16px; }
11.filter button { background: transparent; color: #94a3b8; border: 1.5px solid #334155; padding: 6px 12px; border-radius: 8px; font-size: 13px; cursor: pointer; }
12.filter button.active { background: #fbbf24; color: #0f172a; border-color: #fbbf24; }
13
14ul { list-style: none; }
15li { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: #0f172a; border-radius: 8px; margin-bottom: 6px; }
16li.done span { text-decoration: line-through; color: #64748b; }
17li span { flex: 1; }
18li .del { background: transparent; color: #ef4444; font-size: 20px; border: none; cursor: pointer; padding: 0 8px; }
19
20.empty, .stats { text-align: center; color: #64748b; font-size: 13px; margin-top: 12px; }
Class Todo — ishlaydigan demo
Natijajonli

Mustaqil kengaytirish

0 / 6