uz
Feedback
ToCode

ToCode

Kanalga Telegramโ€™da oโ€˜tish

ื˜ื™ืคื™ื ืงืฆืจื™ื ืœืžืชื›ื ืชื™ื ืžืืช ื™ื ื•ืŸ ืคืจืง

Ko'proq ko'rsatish
1 420
Obunachilar
+124 soatlar
+17 kunlar
-430 kunlar
Postlar arxiv
ToCode
1 420
# ืชื™ืขื“ื•ืฃ ืื—ื“ ื”ืงืฉื™ื™ื ืฉืœ ืขื‘ื•ื“ื” ื‘ืขื•ืœื ื”ืžื•ื“ืจื ื™ ื”ื•ื ืฉืื™ืŸ ืœื” ืกื•ืฃ. ืืฃ ืื—ื“ ืœื ื—ื•ื–ืจ ื”ื‘ื™ืชื” ืขื ื”ืจื’ืฉื” ืฉืœ "ืื™ื–ื” ื›ื™ืฃ ืกื™ื™ืžืชื™ ืืช ื›ืœ ื”ืขื‘ื•ื“ื” ื•ืขื›ืฉื™ื• ืืคืฉืจ ืœื ื•ื—". ืชืžื™ื“ ื™ืฉ ืขื•ื“ ืžื” ืœืขืฉื•ืช ื•ื–ื” ื›ืš ื‘ื›ื•ื•ื ื”. ื•ื”ืงื•ืฉื™ ื”ื•ื ืฉืขื‘ื•ื“ื” ืื™ื ืกื•ืคื™ืช ืžื›ืจื™ื—ื” ืื•ืชื ื• ืœืชืขื“ืฃ, ืœื‘ื—ื•ืจ ื›ืœ ื™ื•ื ืื™ื–ื” ื‘ืขื™ื•ืช ืœืคืชื•ืจ ื•ืื™ื–ื” ื‘ืขื™ื•ืช ืœื”ืฉืื™ืจ ื‘ืฆื“. ื•ืชื™ืขื“ื•ืฃ ืœื ืจืง ืฉืื™ื ื• ื”ืฆื“ ื”ื—ื–ืง ืฉืœื ื•, ืืœื ื’ื ืฉื›ืœ ื”ืฉื ื™ื ื‘ื‘ื™ืช ืกืคืจ ื–ื” ืžืฉื”ื• ืฉืœื ืชืจื’ืœื ื• (ื‘ืฉื‘ื™ืœ ืฆื™ื•ืŸ ื’ื‘ื•ื” ื‘ื‘ื™ืช ืกืคืจ ื”ื™ื” ืฆืจื™ืš ืœืคืชื•ืจ ืืช ื›ืœ ื”ืžื‘ื—ืŸ, ืœื ืœื‘ื—ื•ืจ ืจืง ืืช ื”ื—ืœืงื™ื ื”ื—ืฉื•ื‘ื™ื ืžืžื ื•). ื‘ืจื™ืจืช ื”ืžื—ื“ืœ, ืื• ื”ืชื™ืขื“ื•ืฃ ื”ื ืื™ื‘ื™, ื”ื•ื ืœืคืชื•ืจ ืงื•ื“ื ื›ืœ ืืช ื”ื‘ืขื™ื•ืช ื”ื“ื—ื•ืคื•ืช, ืื—ืจ ื›ืš ืืช ื”ื‘ืขื™ื•ืช ื”ืงืœื•ืช, ื•ื‘ืกื•ืฃ ืืช ื”ื‘ืขื™ื•ืช ื”ืžืกื•ื‘ื›ื•ืช. ื•ื–ื” ื™ื•ืฆืจ ืฉืชื™ ื‘ืขื™ื•ืช: 1. ืขื ื”ื–ืžืŸ ื™ื•ืชืจ ื•ื™ื•ืชืจ ื‘ืขื™ื•ืช ื”ื•ืคื›ื•ืช "ื“ื—ื•ืคื•ืช", ืคืฉื•ื˜ ื‘ื’ืœืœ ืฉื–ืืช ื”ื“ืจืš ื”ื™ื—ื™ื“ื” ืฉืœ ื‘ืขื™ื•ืช (ื•ืฉ ื”ืื ืฉื™ื ืฉืžื™ื™ืฆืจื™ื ืืช ื”ื‘ืขื™ื•ืช) ืœืงื‘ืœ ื™ื—ืก. 2. ืขื ื”ื–ืžืŸ ื‘ืขื™ื•ืช ืžืกื•ื‘ื›ื•ืช ืฆื•ื‘ืจื•ืช "ืจื™ื‘ื™ืช" ื•ื”ื•ืคื›ื•ืช ืœื™ื•ืชืจ ืžืกื•ื‘ื›ื•ืช. ื•ื›ืš ื ื•ืฆืจ ืžืขื’ืœ ืื›ื–ืจื™ ืฉืœ ื›ื™ื‘ื•ื™ ืฉืจื™ืคื•ืช - ื›ื›ืœ ืฉืื ื—ื ื• ืžื›ื‘ื™ื ื™ื•ืชืจ ืฉืจื™ืคื•ืช ื›ืš ื ื•ืฆืจื•ืช ืฉืจื™ืคื•ืช ื™ื•ืชืจ ื’ื“ื•ืœื•ืช, ืฉื“ื•ืจืฉื•ืช ื™ื•ืชืจ ื™ื—ืก ื•ื–ืžืŸ, ืžื” ืฉืœื ืžืฉืื™ืจ ื–ืžืŸ ืœื”ืชืžื•ื“ื“ ืขื ื”ื‘ืขื™ื•ืช ื”ืžืกื•ื‘ื›ื•ืช, ืฉื™ื”ืคื›ื• ื‘ืชื•ืจืŸ ืœื‘ืขื™ื•ืช ื”ืจื‘ื” ื™ื•ืชืจ ื’ื“ื•ืœื•ืช ื•ื“ื—ื•ืคื•ืช. ื”ืคื™ืชืจื•ืŸ ื”ื™ื—ื™ื“, ื•ื’ื ื”ื˜ื•ื‘ ื‘ื™ื•ืชืจ ืœืื ืฉื™ื ืฉืจื•ืฆื™ื ืœื”ืชืงื“ื ื•ืœืฉืžื•ืจ ืขืœ ืื™ื–ื•ืŸ ื‘ื™ืŸ ื”ื—ื™ื™ื ืœืขื‘ื•ื“ื”, ื”ื•ื ืชื™ืขื“ื•ืฃ ื˜ื•ื‘ ื™ื•ืชืจ. ืชื™ืขื“ื•ืฃ ืฉื‘ื• ืื ื—ื ื• ืžื˜ืคืœื™ื ื‘ื‘ืขื™ื•ืช ื”ื—ืฉื•ื‘ื•ืช ื”ื™ื•ื ื›ื“ื™ ืฉื”ืŸ ืœื ื™ืชื”ืคื›ื• ืขืœื™ื ื• ื‘ืขื•ื“ ื—ื•ื“ืฉ ืื• ืฉื ื”. ื“ื‘ืจื™ื ื™ืคืœื•? ื‘ื•ื•ื“ืื™. ื‘ืขื™ื•ืช ื“ื—ื•ืคื•ืช ืœื ื™ืงื‘ืœื• ืžืขื ื”? ืื™ืŸ ืกืคืง. ืื‘ืœ ื”ืืžืช ืฉื–ื” ื›ื‘ืจ ืงื•ืจื” ื‘ื™ืŸ ืื ื ืจืฆื” ื•ื‘ื™ืŸ ืื ืœื. ื‘ื™ืžืžื” ื™ืฉ ืจืง 24 ืฉืขื•ืช, ื•ืœื ืžืฉื ื” ื›ืžื” ืชืขื‘ื“ื• ืงืฉื” ืขื“ื™ื™ืŸ ืชืคืกืคืกื• ื”ืจื‘ื” ื‘ืขื™ื•ืช ื“ื—ื•ืคื•ืช. ืœื ื—ื™ื™ื‘ื™ื ืœืคืชื•ืจ ืืช ื›ืœ ื”ื‘ืขื™ื•ืช. ื—ืฉื•ื‘ ืœืคืชื•ืจ ืืช ื”ื—ืฉื•ื‘ื•ืช.

ToCode
1 420
# ืžื“ืจื™ืš ื•ื™ื“ืื• ื—ื“ืฉ: ืคื™ืชื•ื— ื™ื™ืฉื•ืžื™ Full Stack React ืขื Next.JS 14 ืœืคื ื™ ืฉื‘ื•ืข ื™ืฆืื” ืจืฉืžื™ืช ื’ื™ืจืกื” 14 ืฉืœ next.js. ืฉืชื™ ื”ื’ื™ืจืกืื•ืช ื”ืื—ืจื•ื ื•ืช - 13 ื• 14, ื”ืชืžืงื“ื• ื‘ื™ืฆื™ืจืช ืชืฉืชื™ืช ืœืคื™ืชื•ื— ื™ื™ืฉื•ืžื™ Full Stack ื•ืœืื™ื ื˜ื’ืจืฆื™ื” ื‘ื™ืŸ ืงื•ื“ ืฆื“ ืฉืจืช ืœืงื•ื“ ืฆื“ ืœืงื•ื—. ื”ืขื‘ื•ื“ื” ื”ืชืžืงื“ื” ื‘-2 ืคื™ืฆ'ืจื™ื ืžืจื›ื–ื™ื™ื: ื—ืœื•ืงื” ืœืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“-ืฉืจืช ื•ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“-ืœืงื•ื—, ื•ื™ืฆื™ืจื” ืื•ื˜ื•ืžื˜ื™ืช ืฉืœ API ื‘ืืžืฆืขื•ืช ืžื ื’ื ื•ืŸ Actions. ืฉื ื™ ื”ืžื ื’ื ื•ื ื™ื ืžื‘ื•ืกืกื™ื ืขืœ ื™ื›ื•ืœื•ืช ืชืฉืชื™ืช ืฉืœ ืจื™ืืงื˜ ื•ืžืจื—ื™ื‘ื™ื ื™ื›ื•ืœื•ืช ืืœื”. ื”ืจืขื™ื•ืŸ ื”ื—ื“ืฉ ื”ืจืืฉื•ืŸ ืฉื ื›ื ืก ืขื•ื“ ื‘ next 13 ื”ื•ื ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“ ืฉืจืช, ืื• ื™ื•ืชืจ ื ื›ื•ืŸ ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“-ืฉืจืช ื‘ืœื‘ื“. ืืœื” ืงื•ืžืคื•ื ื ื˜ื•ืช ืจื™ืืงื˜ ืฉืขื•ื‘ืจื•ืช Server Side Rendering ืื‘ืœ ืœื ืขื•ื‘ืจื•ืช Hydration ื‘ื“ืคื“ืคืŸ ื›ืš ืฉืื™ืŸ ืฆื•ืจืš ืœืฉืœื•ื— ืืช ื” JavaScript ืฉืœื”ืŸ ืœื“ืคื“ืคืŸ. ืงื•ืžืคื•ื ื ื˜ื•ืช ืืœื” ืžื•ื’ื“ืจื•ืช ืขืœ ื™ื“ื™ ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ื ื™ื•ืช ื•ื™ื›ื•ืœื•ืช ืœื”ืฉืชืžืฉ ื‘ื›ืœ ื”ื™ื›ื•ืœื•ืช ืฉืœ ืงื•ื“ ืฆื“ ืฉืจืช, ื›ืœื•ืžืจ ืžืฉื”ื• ื‘ืกื’ื ื•ืŸ ื”ื–ื”:
export default () => {
    const users = await listUsers();
    return (
        <p>{users.length} connected users</p>
    );
};
ื›ืืฉืจ listUsers ื™ื›ื•ืœื” ืœื”ื™ื•ืช ืคื•ื ืงืฆื™ื” ืืกื™ื ื›ืจื•ื ื™ืช ืฉืžืชื—ื‘ืจืช ืœื‘ืกื™ืก ื”ื ืชื•ื ื™ื ื•ืžื•ืฉื›ืช ืžืžื ื• ืžื™ื“ืข. ืชื•ืฆืื” ืฉืœ ืงื•ืžืคื•ื ื ื˜ื” ื›ื–ืืช ื”ื™ื ืคืฉื•ื˜ HTML ืœืœื JavaScript ืฉืžืฆื™ื’ ืืช ื”ืชื•ืฆืื”. ื”ืžื ื’ื ื•ืŸ ื”ืฉื ื™ ืฉื ื›ื ืก ื‘ next 14 ืืคื™ืœื• ื™ื•ืชืจ ืžืขื ื™ื™ืŸ - ื”ื•ื ืžืืคืฉืจ ืœืงื•ืžืคื•ื ื ื˜ืช ืฆื“-ืœืงื•ื— "ืœื”ืคืขื™ืœ" ืคื•ื ืงืฆื™ื™ืช ืฆื“ ืฉืจืช ืžืชื•ืš ืงื•ื“ ื˜ื™ืคื•ืœ ื‘ืื™ืจื•ืข, ื›ืœื•ืžืจ ืžืฉื”ื• ื‘ืกื’ื ื•ืŸ ื”ื–ื”:
export default () => {
    const login = async () => {
        const isConnected = await checkUser();
    };
    
    return (
        <button onClick={login}>Login</button>
    );
};
ื›ืืฉืจ checkUser ื”ื™ื ืคื•ื ืงืฆื™ื™ืช ืฆื“ ืฉืจืช ืฉื™ื›ื•ืœื” ืœื”ืชื—ื‘ืจ ืœื‘ืกื™ืก ื”ื ืชื•ื ื™ื ื•ืœืžืฉื•ืš ืžืžื ื• ืžื™ื“ืข. ืคื™ืชื•ื— ืืคืœื™ืงืฆื™ื™ืช React ืขื Next.JS ื”ื™ื•ื ื ื•ืชืŸ ืœื ื• ืืคืฉืจื•ืช ืœื”ืชืžืงื“ ื‘ืงื•ื“ ื”ืžืขืจื›ืช ืขืฆืžื”, ื‘ืœื™ ืฉื ืฆื˜ืจืš ืœื‘ื ื•ืช ืฉื›ื‘ื•ืช ื—ื™ื‘ื•ืจื™ื ื•ืœื”ื’ื“ื™ืจ API ืœื›ืœ ืคืขื•ืœื”. ื”ืžืขืจื›ืช ื’ื ื›ื•ืœืœืช ืžื ื’ื ื•ื ื™ื ืžื•ื‘ื ื™ื ืœื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช ื•ื”ืฆื’ืช ืกื˜ื˜ื•ืก ื›ืš ืฉื”ื›ืœ ืžื—ื•ื‘ืจ ื•ืขื•ื‘ื“ ื™ืฉืจ ืžื”ืงื•ืคืกื. ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ ื”ืžื ื’ื ื•ื ื™ื ื•ืขืœ ืคื™ืชื•ื— ืคืจื•ื™ืงื˜ TypeScript ืขื Next.JS ืฉื›ื•ืœืœ ืงื•ื“ ืฆื“-ืฉืจืช ื•ืฆื“-ืœืงื•ื—, ืžื•ื–ืžื ื™ื ืœืฆืคื•ืช ื‘ืžื“ืจื™ืš ื•ื™ื“ืื• ื—ื“ืฉ ืฉื”ืขืœื™ืชื™. ื‘ืžื“ืจื™ืš ืื ื™ ื‘ื•ื ื” ืคืจื•ื™ืงื˜ ื—ื“ืฉ ืžืืคืก ื”ื›ื•ืœืœ ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“-ืฉืจืช, ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“-ืœืงื•ื— ื•ืืช ื”ื—ื™ื‘ื•ืจ ื‘ื™ื ื™ื”ืŸ ื‘ืขื–ืจืช Actions. ื”ืžื“ืจื™ืš ืกื’ื•ืจ ืœืžื ื•ื™ื™ ื”ืืชืจ ื‘ืœื‘ื“ ืื– ืื ืืชื ื›ื‘ืจ ืžื ื•ื™ื™ื ืคืฉื•ื˜ ื ื›ื ืกื™ื ืœืœื™ื ืง, ื•ืื ืœื ืื– ืื•ืœื™ ื–ืืช ื”ื–ื“ืžื ื•ืช ื˜ื•ื‘ื” ืœื”ืฆื˜ืจืฃ (ื•ื’ื ื–ื” ื‘ืœื—ื™ืฆื” ืขืœ ืื•ืชื• ืœื™ื ืง): https://www.tocode.co.il/boosters/next14-fullstack-react. ื›ืžื• ื›ืŸ ืื ืืชื ืžื ื•ื™ื™ื ืœืืชืจ ื•ื™ืฉ ื ื•ืฉืื™ื ืฉื”ื™ื™ืชื ืฉืžื—ื™ื ืœืฉืžื•ืข ืขืœื™ื”ื ื‘ืžื“ืจื™ื›ื™ ื•ื™ื“ืื• ื ื•ืกืคื™ื ืืœ ืชืชื‘ื™ื™ืฉื• ืœื”ืฉืื™ืจ ื”ื•ื“ืขื” ืื• ืœืฉืœื•ื— ืœื™ ืžื™ื™ืœ.

ToCode
1 420
# ืจื’ืขื™ื ืฉืœ ื”ืืจื” ื‘ืฉื‘ื™ืœ ืจื’ืข ืฉืœ ื”ืืจื” ืœื ืžืกืคื™ืง ืœื”ื™ื—ืฉืฃ ืœืžื™ื“ืข ื—ื“ืฉ ืื• ืœื”ืฉืชื›ื ืข ืฉืžืฉื”ื• ื—ื“ืฉ ื”ื•ื ื ื›ื•ืŸ. ืื™ืŸ ืฉื•ื ื”ืืจื” ื‘ืœืงืจื•ื ืขื•ื“ ืขื•ื‘ื“ื” ืขืœ ื“ื™ื ื•ื–ืื•ืจื™ื ื‘ืื™ื–ื” ืกืคืจ ื˜ื‘ืข, ืื• ื‘ืœื’ืœื•ืช ืื™ืš ืœื›ืชื•ื‘ ืคื•ื ืงืฆื™ื” ืื ื•ื ื™ืžื™ืช ื‘ืกืงืืœื”. ื–ื” ืคืฉื•ื˜ ืขื•ื“ ืคืจื™ื˜ ืžื™ื“ืข ืฉืžืฆื˜ืจืฃ ืœืื™ื ืกื•ืฃ ืคืจื™ื˜ื™ ืžื™ื“ืข ืื—ืจื™ื ื‘ืจืืฉ. ื‘ืฉื‘ื™ืœ ืจื’ืข ืฉืœ ื”ืืจื” ื“ืจื•ืฉ ื’ื ืžืชื— ื•ื“ืจื•ืฉื” ื”ืชื ื’ืฉื•ืช. ื”ืชื ื’ืฉื•ืช ื‘ื™ืŸ ื”ืžื™ื“ืข ื”ื—ื“ืฉ ืœืžืฉื”ื• ืงื™ื™ื. ื’ื™ืœื•ื™ ืฉืชื•ืฆืืชื• ื•ื™ืชื•ืจ ืขืœ ื”ื™ืฉืŸ ื•ื”ื—ืœืคืชื• ื‘ื™ื“ืข ืžืขืžื™ืง ื™ื•ืชืจ. ื—ืฉื‘ื• ืขืœ ื”ืืจื•ืช ื›ืžื• "ืื”ื” - ืขื›ืฉื™ื• ืื ื™ ืžื‘ื™ืŸ ืœืžื” ืฆืจื™ืš Virtual DOM" ืื• "ืื”ื” - ืขื›ืฉื™ื• ืื ื™ ืžื‘ื™ืŸ ืื™ืš ืืคืฉืจ ืœื—ื™ื•ืช ื‘ืœืขื“ื™ื•" ื•ื‘ืขื™ืงืจ "ืขื›ืฉื™ื• ืื ื™ ืžื‘ื™ืŸ ืœืžื” ืžื” ืฉื ื™ืกื™ืชื™ ืœืขืฉื•ืช ืœื ื™ื›ื•ืœ ืœืขื‘ื•ื“". ื•ื”ืืจื•ืช ื“ื•ืจืฉื•ืช ืžืืžืฅ. ื”ืŸ ื“ื•ืจืฉื•ืช ืžืื™ืชื ื• ืœื—ืคืฉ ืœื”ื•ื›ื™ื— ืžื—ื“ืฉ ื›ืœ ื”ื–ืžืŸ ืืช ื”ืืžื™ืชื•ืช ื”ื™ืฉื ื•ืช, ื›ืœ ื”ื–ืžืŸ ืœื—ืฉื•ืฃ ื“ื‘ืจื™ื ืฉื”ืืžื ื• ื‘ื”ื ืืคื™ืœื• ื‘ืฆื•ืจื” ืœื ืžื•ื“ืขืช, ื•ืœื”ื™ื•ืช ืžื•ื›ื ื™ื ืœื”ื™ืคืจื“ ืžืื•ืชืŸ ืืžื™ืชื•ืช ื›ืฉืžื™ื“ืข ื—ื“ืฉ ืžื’ื™ืข. "ื‘ื•ืื™ ื ื ืกื”, ืื•ืœื™ ืื ื™ ื˜ื•ืขื”" ื–ื• ืชืฉื•ื‘ื” ืžืฆื•ื™ื ืช ื›ืฉืื ืฉื™ื ืžืฆื™ืขื™ื ืจืขื™ื•ื ื•ืช ืžื•ื–ืจื™ื (ื›ืžื•ื‘ืŸ ื›ืœ ืขื•ื“ ืืคืฉืจ ืœื’ื“ืจ ืืช ื”ืกื™ื›ื•ืŸ).

ToCode
1 420
# ืœื’ื–ื•ืจ ื•ืœืฉืžื•ืจ: ืื™ืš ืœื”ื•ืจื™ื“ ืืช Google Chrome ื• chromedriver ืžืชืื™ื ืžืชื•ืš Dockerfile ื‘ 2023 ื›ืจื•ื ืขื•ื‘ื“ ืžืžืฉ ื‘ืกื“ืจ ื‘ืžืฆื‘ "ืœืœื ืจืืฉ" ืžืงื•ื ื˜ื™ื™ื ืจ ื“ื•ืงืจ, ื•ื–ื” ื ื•ื— ื›ืฉืจื•ืฆื™ื ืœื”ืจื™ืฅ ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช ืขืœ ืžื—ืฉื‘ ื‘ืœื™ ืžืžืฉืง ื’ืจืคื™. ื™ืฉ ื’ื ืœื ืžืขื˜ ื˜ืžืคืœื™ื™ื˜ื™ื ืฉืœ Dockerfile ื‘ืจืฉืช ืฉืžืจืื™ื ืื™ืš ืœื”ืชืงื™ืŸ ืืช ื›ืจื•ื ื•ืืช ื” chromedriver ื›ื“ื™ ืฉืืคืฉืจ ื™ื”ื™ื” ืœื”ืคืขื™ืœ ืื•ืชื• ืžืชื•ืš ืกืœื ื™ื•ื. ื”ื‘ืขื™ื”? ืจื•ื‘ื ื™ืฉื ื™ื ื•ืœื ืœื•ืงื—ื™ื ื‘ื—ืฉื‘ื•ืŸ ืฉื™ื ื•ื™ ืฉื’ื•ื’ืœ ืขืฉืชื” ืœื ืžื–ืžืŸ ื‘ URL-ื™ื ืœื›ืจื•ืžื“ืจื™ื™ื‘ืจ. ื•ืžืื—ืจ ื•ืื—ืช ื”ืžื˜ืจื•ืช ืฉืœ ื”ื‘ืœื•ื’ ื”ื–ื” ื”ื™ื ืœืขื–ื•ืจ ืœื™ ืœืฉืžื•ืจ ื“ื‘ืจื™ื ื—ืฉื•ื‘ื™ื ื›ื“ื™ ืฉื™ื”ื™ื” ืœื™ ืงืœ ืœืžืฆื•ื ืื•ืชื ืื—ืจื™ (ื•ื›ืŸ ื’ื ืœืฉืชืฃ ืืชื›ื ื‘ืื•ืชื ื”ื“ื‘ืจื™ื ื›ื“ื™ ืฉืœื ืชืฆื˜ืจื›ื• ืœื‘ื–ื‘ื– ืืช ื”ื–ืžืŸ ืฉืื ื™ ื‘ื–ื‘ื–ืชื™) ื–ื” ื” Dockerfile ืฉืขื‘ื“ ืœื™ ื ื›ื•ืŸ ืœื ื•ื‘ืžื‘ืจ 2023 ื›ื“ื™ ืœื”ืชืงื™ืŸ ื•ืœื”ืจื™ืฅ ื›ืจื•ื ื‘ืžืฆื‘ ืœืœื ืจืืฉ ืขืœ ืื•ื‘ื•ื ื˜ื•:
FROM ubuntu:23.04

WORKDIR /app

RUN apt-get update &&\
    apt-get install -y xvfb gnupg wget curl unzip jq ca-certificates --no-install-recommends &&\
    wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - &&\
    echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list &&\
    apt-get update -y && \
    apt-get install -y google-chrome-stable && \
    export CHROMEDRIVER_URL=$(curl https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json|jq -r '.channels.Stable.downloads.chromedriver | .[] | select(.platform == "linux64").url') &&\
    wget -q --continue -P /chromedriver $CHROMEDRIVER_URL &&\
    unzip /chromedriver/chromedriver* -d /chromedriver

# make the chromedriver executable and move it to default selenium path.
RUN chmod +x /chromedriver/chromedriver-linux64/chromedriver
RUN mv /chromedriver/chromedriver-linux64/chromedriver /usr/bin/chromedriver


RUN groupadd -r user && useradd -m -r -g user user && chown -R user /app
USER user

EXPOSE 9222

# default entry point.
CMD ["/usr/bin/google-chrome", "--headless", "--disable-gpu", "--disable-software-rasterizer", "--remote-debugging-port=9222", "--remote-debugging-address=0.0.0.0", "https://www.google.com"]
## end base stage.
ืื—ืจื™ ืฉื‘ื•ื ื™ื ืื•ืชื• ื ืคืขื™ืœ ืขื ื—ื™ื‘ื•ืจ ืคื•ืจื˜ 9222 ื›ื“ื™ ืœืืคืฉืจ ื“ื™ื‘ื’ ืžืžื›ื•ื ื” ืื—ืจืช:
$ docker run --privileged --rm -p 9222:9222 headless-chrome
ื•ืœื‘ืกื•ืฃ ืžื”ืžื—ืฉื‘ ื”ืžืงื•ืžื™ ืฉืœื™ ืื ื™ ืคื•ืชื— ืžื ื”ืจื” ื›ื“ื™ ืฉืืคืฉืจ ื™ื”ื™ื” ืœื“ื‘ื’ ืืช ื”ื›ืจื•ื ื”ืžืจื•ื—ืง:
ssh -L 9222:localhost:9222 user@host-running-the-container.com
ื›ืžื” ื ืงื•ื“ื•ืช ื—ืฉื•ื‘ื•ืช- 1. ื”ืื•ืคืฆื™ื” remote-debugging-address ื‘ืฉื•ืจืช ื”ืคืงื•ื“ื” ืžืืคืฉืจืช ืœื”ืชื—ื‘ืจ ืœืงื•ื ื˜ื™ื™ื ืจ ืžืชื•ืš ื”ืžื›ื•ื ื” ืฉืžืจื™ืฆื” ืื•ืชื• ื›ื“ื™ ืœื“ื‘ื’ ืžืจื—ื•ืง. 2. ื›ืจื•ื ืื•ื”ื‘ ืœื”ืชืœื•ื ืŸ ืฉื™ืฉ ืœื• ืžืฆื‘ headless ื—ื“ืฉ ื•ืฆืจื™ืš ืœื”ืคืขื™ืœ ืื•ืชื• ืขื ื”ืื•ืคืฆื™ื” headless=new. ื”ื ืœื ืžืกืคืจื™ื ืฉืื ืชืขืฉื• ืืช ื–ื” ืื– remote-debugging-adress ื™ืคืกื™ืง ืœืขื‘ื•ื“ ื•ืื™ ืืคืฉืจ ื™ื”ื™ื” ืœื“ื‘ื’ ืžืจื—ื•ืง. 3. ืœื’ื•ื’ืœ ื”ื™ื” ืคืขื ืžื ื’ื ื•ืŸ ื“ื™ ืžืกื•ืจื‘ืœ ื›ื“ื™ ืœื’ืœื•ืช ืื™ื–ื” ื’ื™ืจืกื” ืฉืœ chromedriver ืฆืจื™ืš ืœื”ื•ืจื™ื“. ื”ื ื”ื—ืœื™ืคื• ืืช ื–ื” ื‘ endpoint ืื—ื“ ืฉืžื—ื–ื™ืจ JSON ืขื ื›ืœ ื”ืžื™ื“ืข. ื•ืื ื™ืฉ ืœื›ื ืขื•ื“ ื˜ื™ืคื™ื ืขืœ ื”ืจืฆืช ื›ืจื•ื ืœืœื ืจืืฉ ืžืชื•ืš ื“ื•ืงืจ ืžื•ื–ืžื ื™ื ื‘ื—ื•ื ืœื”ืฉืื™ืจ ื›ืืŸ ื‘ืชื’ื•ื‘ื•ืช.

ToCode
1 420
# ื”ื™ื•ื ืœืžื“ืชื™: CSS Nesting ื›ื‘ืจ ืขื•ื‘ื“ ื‘ื“ืคื“ืคืŸ ืื™ืคืฉื”ื• ื‘ืขื‘ืจ ื”ืจื—ื•ืง ืžื™ืฉื”ื• ืกื™ืคืจ ืœื™ ืขืœ Less ื• Sass ื•ืื™ืš ืฉื•ื•ื” ืœื”ืฉืชืžืฉ ื‘ื”ื ื›ื™ ืืคืฉืจ ืœื›ืชื•ื‘ ืกืœืงื˜ื•ืจ ื‘ืชื•ืš ืกืœืงื˜ื•ืจ ื•ื–ื” ื”ื™ื” ืžืื•ื“ ืžืจื’ืฉ ื‘ืฉืขืชื•. ืขื ื”ื–ืžืŸ ื ืคืจื“ื ื• ืž Less ื•ืœืžื“ื ื• ืœืงื‘ืœ ืืช Sass ื•ื ื›ื•ืŸ ืฉืœื™ืžื™ื ื’ื ื”ื•ื ื”ื•ื—ืœืฃ ื‘ CSS In JS ื•ื‘ Tailwind ืื‘ืœ ืขื“ื™ื™ืŸ ื™ืฉ ืžืฉื”ื• ืงืกื•ื ื‘ืœื›ืชื•ื‘ CSS ื•ื™ืฉ ืขื“ื™ื™ืŸ ืœื ืžืขื˜ ืคืจื•ื™ืงื˜ื™ื ืขื ืงื‘ืฆื™ css. ืขื›ืฉื™ื• ื ื›ื•ืŸ Sass ื›ื•ืœืœ ื”ืžื•ืŸ ื”ืžื•ืŸ ืคื™ืฆ'ืจื™ื ื•ืงื™ื ื•ืŸ ืกืœืงื˜ื•ืจื™ื ื”ื•ื ืจืง ืื—ื“ ืžื”ื, ืื‘ืœ ืขื“ื™ื™ืŸ ืงืฉื” ืœื“ืžื™ื™ืŸ ืฉ Sass ื‘ื›ืœืœ ื”ื™ื” ื ื•ืœื“ ืื ืกืœืงื˜ื•ืจื™ื ืžืงื•ื ื ื™ื ื•ืžืฉืชื ื™ื ื”ื™ื• ืขื•ื‘ื“ื™ื ื‘ 2006. ืื‘ืœ ืื ื—ื ื• ื›ื‘ืจ ืœื ื‘ 2006 ื•ืืคื™ืœื• ืœื ื‘ 2016. ืžืฉืชื ื™ื ื‘ CSS ื›ื‘ืจ ืขื•ื‘ื“ื™ื ืžื–ืžืŸ ื•ื”ื™ื•ื ื‘ืžืงืจื” ื’ื™ืœื™ืชื™ ืฉื’ื ืกืœืงื˜ื•ืจื™ื ืžืงื•ื ื ื™ื ื›ื‘ืจ ืขื•ื‘ื“ื™ื ื‘ืจื•ื‘ ื”ื“ืคื“ืคื ื™ื ื”ืžื•ื“ืจื ื™ื™ื. ืื™ืš ื–ื” ื ืจืื”? ื ื• ื›ืžืขื˜ ื›ืžื• ืฉื–ื” ื ืจืื” ื‘ Sass, ืจืง ื‘ืœื™ ื”ืคืจื™ืงื•ืžืคื™ื™ืœืจ. ืงื•ื“ HTML:
<form>
  <label for="name">Name:
    <input type="text" id="name" />
  </label>
  <label for="email">email:</label>
  <input type="text" id="email" />
</form>
ืงื•ื“ CSS:
input {
  /* styles for input not in a label  */
  border: tomato 2px solid;
}
label {
  /* styles for label */
  font-family: system-ui;
  font-size: 1.25rem;
  input {
    /* styles for input in a label  */
    border: blue 2px dashed;
  }
}
ื•ืœื™ื™ื‘ ืงื•ื“ืคืŸ: <iframe height="300" style="width: 100%;" scrolling="no" title="Untitled" src="https://codepen.io/ynonp/embed/abXZbvo?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/ynonp/pen/abXZbvo"> Untitled</a> by Ynon Perek (<a href="https://codepen.io/ynonp">@ynonp</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> https://codepen.io/ynonp/pen/abXZbvo ืœื›ืœ ื”ืคืจื˜ื™ื ื•ื”ื”ื‘ื“ืœื™ื ืžื•ืœ Sass ืฉื•ื•ื” ืœื”ืขื™ืฃ ืžื‘ื˜ ื‘ืชื™ืขื•ื“ ื‘ืงื™ืฉื•ืจ: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting

ToCode
1 420
# ื˜ื™ืค JavaScript - ื ื™ืกื•ื™ ืขื ืขืจืš ื‘ืจื™ืจืช ืžื—ื“ืœ ื‘ืขื‘ื•ื“ื” ืขื ืงื•ื“ ืืกื™ื ื›ืจื•ื ื™ ื‘ JavaScript ื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช ื”ื•ื ื”ื›ืจื—ื™, ื”ื‘ืขื™ื” ืฉื”ืžื ื’ื ื•ืŸ ื”ืงื™ื™ื ื‘ืฉืคื” ืœื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช ื‘ืงื•ื“ ืืกื™ื ื›ืจื•ื ื™ ืงืฆืช ืžืกื•ืจื‘ืœ. ื ืชื‘ื•ื ืŸ ื‘ืงื•ื“ ื”ื‘ื:
async function sleepOrDie(ms, result) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.5) {
        resolve(result);
      } else {
        reject();
      }
    }, ms)
  })
}

async function handleClick() {
  const value = await sleepOrDie(50, 10);
  alert(value);
}

document.querySelector('button').addEventListener('click', handleClick);
ืื ื™ ื™ื•ื“ืข ืœื ืžืชื•ื—ื›ื ื‘ืžื™ื•ื—ื“ ืื‘ืœ ืžืกืคื™ืง ื‘ืฉื‘ื™ืœ ื”ื“ื’ืžื”. ืื ื”ืคื•ื ืงืฆื™ื” ื”ืืกื™ื ื›ืจื•ื ื™ืช ืžืฆืœื™ื—ื” ืื– ืžืงื‘ืœื™ื ืขืจืš, ืื‘ืœ ืื ื”ื™ื ื ื›ืฉืœืช ื ื–ืจืง Exception. ื–ื” ืขื•ื‘ื“ ืื ื”ื˜ื™ืคื•ืœ ืฉืœื ื• ื‘ืฉื’ื™ืื•ืช ื”ื•ื ื‘ flow ืื—ืจ ื•ืื– catch ื™ื•ื›ืœ ืœื”ืคืขื™ืœ ืืช ืื•ืชื• flow. ืื‘ืœ ืžื” ืื ืื ื™ ืคืฉื•ื˜ ืจื•ืฆื” ืœืชืช ืœ value ืขืจืš ื‘ืจื™ืจืช ืžื—ื“ืœ ืื ื”ื™ืชื” ืฉื’ื™ืื”? ืœืžืฉืœ ืื ืื ื™ ืžื ืกื” ืœืงืจื•ื ืขืจืš ืžื‘ืกื™ืก ื ืชื•ื ื™ื ืื• ืžื”ื’ื“ืจื•ืช ืžืฉืชืžืฉ ื•ืื ื”ืขืจืš ืœื ืฉื ื”ื›ืœ ื‘ืกื“ืจ ื•ื”ืงื•ื“ ืžืžืฉื™ืš ืขื ืื•ืชื” ื‘ืจื™ืจืช ืžื—ื“ืœ. ื‘ืžืฆื‘ ื›ื–ื” try/catch ื™ื›ื•ืœ ืœื”ื™ืจืื•ืช ืžืกื•ืจื‘ืœ:
async function handleClick() {
  let value = 0;
  try {
    value = await sleepOrDie(50, 10);
  } catch (err) {
    
  }
  alert(value);
}
ืžื‘ื—ื™ื ืช ื ื›ื•ื ื•ืช ื”ืงื•ื“ ื˜ื•ื‘ ื™ื•ืชืจ, ืื‘ืœ ืžื‘ื—ื™ื ืช ื”ืชื—ื‘ื™ืจ ื–ื” ืคืฉื•ื˜ ื ืจืื” ืจืข: ื” const ื”ืคืš ืœ let ืœื’ืžืจื™ ื‘ืœื™ ืกื™ื‘ื”, ื•ืื ื™ ืชืงื•ืข ืขื ื‘ืœื•ืง catch ืจื™ืง. ื˜ื›ื ื™ืงื” ื˜ื•ื‘ื” ื›ื“ื™ ืœื”ืกืชื™ืจ ืงื•ื“ ืžื›ื•ืขืจ ื”ื™ื ืœื–ืจื•ืง ืื•ืชื• ืœืคื•ื ืงืฆื™ื”. ืจื™ืคืงื˜ื•ืจื™ื ื’ ืงืฆืจ ื•ื ืงื‘ืœ:
async function tryOr(fn, args, defaultValue) {
  try {
    return await fn.apply(null, args);
  } catch (err) {
    return defaultValue;
  } 
}

async function handleClick() {
  const value = await tryOr(sleepOrDie, [50, 10], 0);
  alert(value);
}
ื•ืžื™ื˜ื™ื‘ื™ ืœื›ืช ื™ื›ื•ืœื™ื ืœื”ื•ืกื™ืฃ ืืช ื”ืคื•ื ืงืฆื™ื” ื”ื–ื• ืœืคืจื•ื˜ื•ื˜ื™ื™ืค ืฉืœ ืคื•ื ืงืฆื™ื” ื‘ JavaScript ื›ื“ื™ ืฉืชื”ื™ื” ื–ืžื™ื ื” ืœื ื• ื‘ื›ืœ ืžืงื•ื ื‘ืชื•ื›ื ื™ืช:
Function.prototype.tryOr = async function (args, defaultValue) {
  try {
    return await this.apply(null, args);
  } catch (err) {
    return defaultValue;
  }
}


async function handleClick() {
  const value = await sleepOrDie.tryOr([50, 10], 0);
  alert(value);
}

ToCode
1 420
# ื”ืฆืฆื” ืœืขืชื™ื“: ืคืขื•ืœื•ืช ืฆื“ ืฉืจืช ื‘ืจื™ืืงื˜ ื• Next.js 14 ืœืคื ื™ ื›ืžื” ื™ืžื™ื ื›ืชื‘ืชื™ ื›ืืŸ ืขืœ ืคืขื•ืœื•ืช ืฆื“-ืœืงื•ื—, ืคื™ืฆ'ืจ ื—ืžื•ื“ ืฉืœ ืจื™ืืงื˜ ืฉื”ื•ืœืš ืœื—ืกื•ืš ืœื ื• ื›ืžื” ื”ืงืœืงื•ืช ื‘ื›ืชื™ื‘ืช ืงื•ื“ ืฉืžื˜ืคืœ ื‘ื˜ืคืกื™ื. ื”ื—ืœืง ื”ืฉื ื™ ืฉืœื•, ืฉื ืงืจื Server Actions, ื›ื‘ืจ ื”ืจื‘ื” ื™ื•ืชืจ ืžื”ืคื›ื ื™ ื•ื“ื•ืจืฉ ืชืžื™ื›ื” ืžืคืจื™ื™ืžื•ื•ืจืง ื‘ืฆื“ ืฉืจืช. ื‘ื–ื›ื•ืช Next.JS 14 ืฉื™ืฆื ืขื›ืฉื™ื• ื ื•ื›ืœ ืœืจืื•ืช ืื™ืš ื–ื” ืขื•ื‘ื“ ื•ืœื”ื‘ื™ืŸ ืืช ื”ื›ื™ื•ื•ืŸ ืฉืœ ืจื™ืืงื˜ ื‘ืชื•ืจ Full Stack Framework. ## ื”ืกื™ืคื•ืจ ืžืื—ื•ืจื™ ืคืขื•ืœื•ืช ืฆื“-ืฉืจืช ื”ืŸ ืžื ื’ื ื•ืŸ ืฉื‘ื• ืงื•ืžืคื•ื ื ื˜ื” ืจื™ืืงื˜ื™ืช ืžื’ื™ืฉื” ื˜ื•ืคืก ืœืฉืจืช, ื•ื›ืœ ืชื”ืœื™ืš ื”ื’ืฉืช ื”ื˜ื•ืคืก ื•ืงื‘ืœืช ื”ืชืฉื•ื‘ื” ืžื ื•ื”ืœ ืขืœ ื™ื“ื™ ื”ืคืจื™ื™ืžื•ื•ืจืง. ื‘ื›ืชื™ื‘ืช ืคืขื•ืœื•ืช ืฆื“ ืฉืจืช ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื›ืชื•ื‘ ืจืง ืฉื ื™ ื“ื‘ืจื™ื: 1. ืืช ืงื•ื“ ื”ืงื•ืžืคื•ื ื ื˜ื”, ื›ื•ืœืœ ืฉื™ืžื•ืฉ ื‘ Hook ืžื™ื•ื—ื“ ื›ื“ื™ ืœื”ืฆื™ื’ ืžืžืฉืง ืฉื•ื ื” ืœืžืฆื‘ ื˜ืขื™ื ื”. 2. ืืช ื”ืคื•ื ืงืฆื™ื” ื‘ืฉืจืช (ื‘ node.js) ืฉืžื˜ืคืœืช ื‘ื”ื’ืฉืช ื”ื˜ื•ืคืก. ื›ืœ ื”ื ื•ืฉื ืฉืœ ืฉืœื™ื—ืช ื”ื•ื“ืขื” ื‘ http, ืกืจื™ืืœื™ื–ืฆื™ื” ืฉืœ ื”ืคืจืžื˜ืจื™ื, ื”ืžืชื ื” ื•ืคื™ืขื ื•ื— ืชืฉื•ื‘ื•ืช ืžื‘ื•ืฆืข ื‘ืฆื•ืจื” ืื•ื˜ื•ืžื˜ื™ืช ืขืœ ื™ื“ื™ ื”ืคืจื™ื™ืžื•ื•ืจืง. ## ื“ื•ื’ืžืช ืงื•ื“ ืงื•ื“? ื‘ืจื•ืจ. ื‘ืคืจื•ื™ืงื˜ next.js ืื ื—ื ื• ืฆืจื™ื›ื™ื ื‘ืกืš ื”ื›ืœ ืฉื ื™ ืงื‘ืฆื™ื. ื”ืงื•ื‘ืฅ page.tsx ืขื ื”ืงื•ืžืคื•ื ื ื˜ื” ืฉืœ ื”ืขืžื•ื“ ื•ื”ืงื•ื‘ืฅ server_actions.ts ืฉืžื’ื“ื™ืจ ืืช ื”ืงื•ื“ ืฉืžื˜ืคืœ ื‘ื˜ื•ืคืก ื‘ืฆื“ ื”ืฉืจืช. ื‘ืงื•ื‘ืฅ server_actions.ts ืื ื™ ื›ื•ืชื‘:
'use server'
const process = require('node:process');

export async function createItem(data: FormData) {
  console.log(`Client sent form: ${JSON.stringify(Object.fromEntries(data))}`);
  console.log(`I'm a server action pid = ${process.pid}`);
  await new Promise((resolve, reject) => {
    setTimeout(resolve, 3000)
  });
  return `${process.pid}/${data.get('name')}`
}
ื”ืชื—ื™ืœื™ืช 'use server' ืื•ืžืจืช ืœ next.js ืฉืืช ื”ืคื•ื ืงืฆื™ื” ื”ื–ืืช ืฆืจื™ืš ืœื”ืจื™ืฅ ื‘ืฆื“ ืฉืจืช. ื”ืคื•ื ืงืฆื™ื” ืขืฆืžื” ืžืฉืชืžืฉืช ื‘ื“ื‘ืจื™ื ืฉืœ ืฆื“ ืฉืจืช ืœื“ื•ื’ืžื” process.pid, ื•ืžืงื‘ืœืช ื‘ืชื•ืจ ืงืœื˜ ืžืฉื”ื• ืžืกื•ื’ FormData - ืืœื” ื”ืขืจื›ื™ื ื‘ื˜ื•ืคืก ืฉื™ื’ื™ืขื• ืžื”ืœืงื•ื—. ื‘ืงื•ื‘ืฅ page.tsx ื™ื”ื™ื” ืœื™ ืงื•ื“ ืงืฆืช ื™ื•ืชืจ ืืจื•ืš ืฉืžื’ื“ื™ืจ ืฉืชื™ ืงื•ืžืคื•ื ื ื˜ื•ืช. ื”ืงื•ืžืคื•ื ื ื˜ื” ื”ืจืืฉื•ื ื” ื”ื™ื ื”ื˜ื•ืคืก:
export default function Page() {
  const [id, setId] = useState('');

  async function onSubmit(formData: FormData) {
    const nextId = await createItem(formData);
    setId(nextId);
  }
  return (
    <form action={onSubmit}>
      <Header />
      {id != '' && <p>Ready. Id = {id}</p>}
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}
ืื ื™ ืžื’ื“ื™ืจ action ืœื˜ื•ืคืก ื•ื‘ืชื•ืš ื”ืคื•ื ืงืฆื™ื” ืคืฉื•ื˜ ืžืคืขื™ืœ ืืช ื”ืคื•ื ืงืฆื™ื” ืž server_actions.ts ื•ืฉื•ืžืจ ืืช ื”ืชืฉื•ื‘ื” ืœืžืฉืชื ื”. ืžืื—ื•ืจื™ ื”ืงืœืขื™ื ืจื™ืืงื˜ ื™ืฉืœื— ืืช ื”ื˜ื•ืคืก ืœืฉืจืช, ื”ืคื•ื ืงืฆื™ื” ืชืจื•ืฅ ื‘ืฉืจืช ื•ืชื—ื–ื™ืจ ืืช ื”ืชื•ืฆืื” ื‘ืชืฉื•ื‘ื” ืœื‘ืงืฉื”, ื”ื›ืœ ื“ืจืš ื”ืจืฉืช ื•ืขื ืกืจื™ืืœื™ื–ืฆื™ื” ืื•ื˜ื•ืžื˜ื™ืช. ื‘ืฉื‘ื™ืœ ืœื”ืฆื™ื’ ืžืกืš ื˜ืขื™ื ื” ื›ืฉื”ืžื™ื“ืข ื ืฉืœื— ืœืฉืจืช ื‘ื ื™ืชื™ ืืช ื”ืงื•ืžืคื•ื ื ื˜ื” Header ืขื ื”ืงื•ื“ ื”ื‘ื:
function Header() {
  const status = useFormStatus()

  if (status.pending) {
    return <p>Loading...</p>
  }
}
ื”ืคื•ื ืงืฆื™ื” useFormStatus ื”ื’ื™ืขื” ืž react-dom (ืจืง ื‘ื’ื™ืจืกืื•ืช ื—ื“ืฉื•ืช ืฉืœ ืจื™ืืงื˜), ื•ืžื—ื–ื™ืจื” ืื•ื‘ื™ืงื˜ ืขื ืžืกืคืจ ืฉื“ื•ืช ืฉืžืกืคืจ ืžื” ืžืฆื‘ ื”ื’ืฉืช ื”ื˜ื•ืคืก ื”ืื—ืจื•ืŸ ืฉื”ื•ื’ืฉ. ืฉื•ืจื” ืชื—ืชื•ื ื” ืžื ื’ื ื•ืŸ Server Actions ื”ื•ืคืš ืืช ืจื™ืืงื˜ ืœื”ืจื‘ื” ื™ื•ืชืจ ืคืจื™ื™ืžื•ื•ืจืง ืžืœื ืœืคื™ืชื•ื— Full Stack ืžืืฉืจ ืกืคืจื™ื” ืงื˜ื ื” ื•ื’ืžื™ืฉื” ืœืคื™ืชื•ื— ืฉื›ื‘ืช ื”ืชืฆื•ื’ื”. ื™ื”ื™ื” ืžืขื ื™ื™ืŸ ืœืจืื•ืช ืืช ื”ื”ืฉืœื›ื•ืช ืฉืœ ื–ื” ืขืœ ื”ืืงื•ืกื™ืกื˜ื. ืžืฆื“ ืื—ื“ ืื™ืŸ ืกืคืง ืฉื”ืจื‘ื” ื™ื•ืชืจ ืงืœ ืœื‘ื ื•ืช ืคืจื•ื™ืงื˜ Full Stack ืžืืคืก ื›ืฉื›ืœ ื”ื›ืœื™ื ืžื ื’ื ื™ื ื™ืคื” ื™ื—ื“, ืื‘ืœ ืžืฆื“ ืฉื ื™ ื”ืจื‘ื” ืื ืฉื™ื (ื›ื•ืœืœ ืื ื™) ื™ืชื’ืขื’ืขื• ืœื’ืžื™ืฉื•ืช ื”ืžื™ื ื™ืžืœื™ืกื˜ื™ืช ืฉืœ ืจื™ืืงื˜ ื”ื™ืฉืŸ ื•ื”ื˜ื•ื‘. ื ืžืฉื™ืš ืœืขืงื•ื‘.

ToCode
1 420
# ื”ื™ื•ื ืœืžื“ืชื™: ื”ืคืœื•ืก ื”ืงื˜ืŸ ื‘ืกืงืืœื” ื‘ื•ืื• ื ื›ืชื•ื‘ ืชื•ื›ื ื™ืช ืกืงืืœื” ืฉืžื—ื–ื™ืงื” "ื“ื‘ืจื™ื" ืฉื™ื›ื•ืœื™ื ืœื”ื™ืฉืžืจ ืœืฉืจืช ืžืจื•ื—ืง. ืืคืฉืจ ืœื“ืžื™ื™ืŸ ืงืœืืก ืฉืœ ืžืฉืชืžืฉ ืฉื™ืจืื” ื›ืš:
case class User(name: String)
ื•ืื•ืœื™ ืงืœืืก ืฉืœ ืžืกืžืš:
class Document(title: String, content: String)
ื‘ืฉื‘ื™ืœ ืœืฉืžื•ืจ ืื•ืชื ืœืฉืจืช ืžืจื•ื—ืง ืื ื™ ืฆืจื™ืš ืœื”ื•ืกื™ืฃ ืœื›ืœ ืื—ื“ ืžื”ื url, ื•ื‘ืฉื‘ื™ืœ ืœื ืœืฉื ื•ืช ืืช ื”ืงืœืืกื™ื ืื ื™ ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ Generic ื•ืœื™ืฆื•ืจ ื’ื™ืจืกื” "ืžืจื•ื—ืงืช" ืฉืœื”ื, ื›ืœื•ืžืจ:
case class Remote[S](value: S, url: String)
ืื– ืขื›ืฉื™ื• ืžืฉื”ื• ืฉื”ื•ื Remote[User] ื™ื—ื–ื™ืง ืฉื“ื” ื‘ืฉื value ืžืกื•ื’ User ื•ื’ื ืฉื“ื” ื‘ืฉื url ืžืกื•ื’ String. ื•ืื•ืœื™ ื ืจืฆื” ืœื›ืชื•ื‘ ืคื•ื ืงืฆื™ื” ื›ืœืœื™ืช ืฉื™ื›ื•ืœื” ืœืงื‘ืœ ืžืฉื”ื• ืฉื”ื•ื Remote ื•ืœืฉืžื•ืจ ืืช ื”ืขืจืš ืž value ืœืฉืจืช ื”ืžืจื•ื—ืง ื‘ืืžืฆืขื•ืช HTTP Post. ื”ื™ื™ื ื• ืขืฉื•ื™ื™ื ืœื—ืฉื•ื‘ ืฉื”ื—ืชื™ืžื” ืฉืœ ืคื•ื ืงืฆื™ื” ื›ื–ื• ืชื™ืจืื” ื›ืš:
def save(what: Remote[Any]): Unit =
  println(s"Saving ...")
ืื‘ืœ ืื ื ื ืกื” ืœื™ืฆื•ืจ ืžืฉืชืžืฉ ื•ืœืฉืžื•ืจ ืื•ืชื• ื ืงื‘ืœ ืฉื’ื™ืืช ืงื•ืžืคื™ืœืฆื™ื”. ื›ืœื•ืžืจ ื”ืงื•ื“ ื”ื‘ื:
@main def main()=
  val a = Remote[User](value = User("ynon"), url = "/admin")
  save(a)
ืœื ืžืฆืœื™ื— ืœื”ืชืงืžืคืœ ื‘ื’ืœืœ ื”ืฉื’ื™ืื”:
Found:    (a : Remote[User])
Required: Remote[Any]
  save(a)
ืžื” ืงืจื” ื›ืืŸ? ื”ืคื•ื ืงืฆื™ื” ืžืฆืคื” ืœืงื‘ืœ ืžืฉื”ื• ืžื˜ื™ืคื•ืก Remote[Any]. ื ื›ื•ืŸ ืฉ User ื”ื•ื ืกื•ื’ ืฉืœ Any ื•ืื ื”ื™ืชื” ืœื ื• ืคื•ื ืงืฆื™ื” ืฉืžืงื‘ืœืช Any ืœื ื”ื™ืชื” ื‘ืขื™ื” ืœื”ืขื‘ื™ืจ ืœื” ืžืฉื”ื• ืžืกื•ื’ User, ืื‘ืœ ื‘ืื•ืคืŸ ืจื’ื™ืœ Remote[User] ืื™ื ื ื• ืžืฉื”ื• ืžืกื•ื’ Remote[Any]. ืคื™ืชืจื•ืŸ? ืœืžืขืฉื” ืฉื ื™ื™ื. ื”ื›ื™ ืงืœ ืœื”ื’ื“ื™ืจ ืืช ื”ืคื•ื ืงืฆื™ื” ื‘ืชื•ืจ ืคื•ื ืงืฆื™ื” ื’ื ืจื™ืช ื•ืœื ืœื”ืชืขืกืง ืขื ื™ืจื•ืฉื” ื›ืœื•ืžืจ ื ืฉื ื” ืืช save ืœ:
def save[S](what: Remote[S]): Unit =
  println(s"Saving ...${what.value} to ${what.url}")
ื•ื”ื›ืœ ืžืชืงืžืคืœ ื•ืขื•ื‘ื“. ื”ืคื™ืชืจื•ืŸ ื”ืฉื ื™ ื•ื”ื•ื ื”ืกื™ืคื•ืจ ืฉืœ ื”ืคื•ืกื˜ ื”ื–ื” ื ื•ืขื“ ืœืžืงืจื™ื ื‘ื”ื ืœื ื”ืฆืœื—ืชื ืœื”ืคื•ืš ืืช ื”ืคื•ื ืงืฆื™ื” ืœื’ื ืจื™ืช ืžื›ืœ ืžื™ื ื™ ืกื™ื‘ื•ืช ืื• ืฉื™ืฉ ืœื›ื Use Case ื˜ื™ืคื” ืฉื•ื ื”, ื•ืืชื ื‘ืืžืช ืจื•ืฆื™ื ืœื”ื’ื™ื“ ืžืฉื”ื• ืื—ืจ ืขืœ ื”ื˜ื™ืคื•ืก Remote[S] - ื”ื™ื™ืชื ืจื•ืฆื™ื ืœื”ื’ื™ื“ ืฉืื ื™ืฉ ืœื›ื ืคื•ื ืงืฆื™ื” ืฉืžืฆืคื” ืœืงื‘ืœ Remote[S] ืœื ืžืฉื ื” ืžื” ื–ื” S, ื•ื™ืฉ ืœื›ื ืžืฉื”ื• ืื—ืจ ื ืงืจื ืœื• T ืฉื™ื•ืจืฉ ืž S, ืื– Remote[T] ื™ื™ืจืฉ ืž Remote[S]. ื•ื‘ืฉื‘ื™ืœ ืœื”ื’ื™ื“ ืืช ื–ื” ื‘ืกืงืืœื” ืืคืฉืจ ืœื”ื•ืกื™ืฃ ืกื™ืžืŸ + ืœืคื ื™ ื” S ื‘ื”ื’ื“ืจืช ื”ื˜ื™ืคื•ืก ื”ื’ื ืจื™. ื–ื” ื ืจืื” ื›ืš:
case class Remote[+S](value: S, url: String)
case class User(name: String)
class Document(title: String, content: String)

def save(what: Remote[Any]): Unit =
  println(s"Saving ...${what.value} to ${what.url}")

@main def main()=
  val x: Any = User("ynon")
  val a = Remote[User](value = User("ynon"), url = "/admin")
  save(a)
ื•ื’ื ื”ื’ื™ืจืกื” ื”ื–ื• ืžืชืงืžืคืœืช ื•ืขื•ื‘ื“ืช. ื•ืœื™ื ืง ืื—ืจื•ืŸ ืœืกืงืจื ื™ื ืฉืจื•ืฆื™ื ืœืงืจื•ื ืขื•ื“ ืขืœ ื”ืžื ื’ื ื•ืŸ ื”ื–ื” ื‘ืชื™ืขื•ื“ ืฉืœ ืกืงืืœื”, ืขืœ ื”ืžื™ื ื•ืก ืฉืืคืฉืจ ืœืจืฉื•ื ื‘ืžืงื•ื ื”ืคืœื•ืก, ื•ืขืœ ื”ืฉืžื•ืช ื‘ืื ื’ืœื™ืช ืฉืœ ืฉื ื™ื”ื ื™ื”ื™ื” ืชื™ืขื•ื“ Variances ืžื”ืกื™ื•ืจ ื‘ืกืงืืœื”: https://docs.scala-lang.org/tour/variances.html

ToCode
1 420
# ืจื™ืืงื˜ ืžื‘ื˜ ืœืขืชื™ื“ - ืคืขื•ืœื•ืช ืฆื“ ืœืงื•ื— ืื—ื“ ื”ื“ื‘ืจื™ื ื”ืžืขื™ื™ืคื™ื ื‘ืจื™ืืงื˜ ืชืžื™ื“ ื”ื™ื” ื”ื—ื™ื‘ื•ืจ ื‘ื˜ื•ืคืก ื‘ื™ืŸ State ืœืชื•ื›ืŸ ืฉืœ ืจื›ื™ื‘ื™ ื”ืงืœื˜. ืื™ื ืกืคื•ืจ ืกืคืจื™ื•ืช ื ื›ืชื‘ื• ื›ื“ื™ ืœืขื‘ื•ื“ ื˜ื•ื‘ ื™ื•ืชืจ ืขื ื˜ืคืกื™ื, ื•ืื™ื ืกืคื•ืจ ืžืชื›ื ืชื™ื ื•ืžืชื›ื ืชื•ืช ื”ืชื’ืขื’ืขื• ืœืื™ื–ื” ng-model ืฉื™ื—ืกื•ืš ืœื ื• ืืช ื›ืื‘ ื”ืจืืฉ. ื•ื‘ื“ื™ื•ืง ื›ืฉื›ืžืขื˜ ืื™ื‘ื“ื ื• ืชืงื•ื•ื” ื”ื’ื™ืขื• ื“ืŸ ืื‘ืจืžื•ื‘ ื•ืฆื•ื•ืช ื”ื—ื‘ืจื™ื ืขื ืคื™ืฆืณืจ ื—ื“ืฉ ืฉืื•ืœื™ ืงืฆืช ื™ืขื–ื•ืจ ืœื—ืกื•ืš ื—ืœืง ืžืขื‘ื•ื“ืช ื”ื—ื™ื‘ื•ืจ ืฉืœ ื”ื˜ืคืกื™ื - ื•ื–ื”ื• Client Side Form Actions. ื–ื” ืขื•ื‘ื“ ื›ื›ื”: 1. ืืคืฉืจ ื™ื”ื™ื” ืœื”ื’ื“ื™ืจ ืœืืœืžื ื˜ form ืžืืคื™ื™ืŸ action ืฉื™ื”ื™ื” ืคื•ื ืงืฆื™ื” ืืกื™ื ื›ืจื•ื ื™ืช. 2. ืคื•ื ืงืฆื™ื” ื–ื• ืชื•ืคืขืœ ื›ืฉืžื™ืฉื”ื• ื™ื ืกื” ืœื”ื’ื™ืฉ ืืช ื”ืชื•ื›ืŸ, ื•ืชื•ื›ืœ ืœืขื“ื›ืŸ State. 3. ืื ื”ืคื•ื ืงืฆื™ื” ื–ื•ืจืงืช ืฉื’ื™ืื” ื”ืฉื’ื™ืื” ืชื™ื—ืฉื‘ ื›ืฉื’ื™ืืช render ื•ืชื™ืชืคืก ื‘ Error Boundary ื”ืงืจื•ื‘. ืงื•ื“? ื‘ื˜ื— ื”ื ื” ื”ื“ื•ื’ืžื”:
import { useState } from "react";

export default function Todo() {
  const [name, setName] = useState([]);
  async function copy(formData) {
    console.log(formData);
    setName(formData.get("name"));
  }
  return (
    <>
      <form action={copy}>
        <label>
          Type your name:
          <input name="name" />
        </label>
        <button type="submit">submit</button>
      </form>
      <p>Hello {name}</p>
    </>
  );
}
ื›ืฉืœื•ื—ืฆื™ื submit ืžื•ืคืขืœืช ื”ืคื•ื ืงืฆื™ื” ืฉืžืขื“ื›ื ืช ืืช ืžืฉืชื ื” ื”ืกื˜ื™ื™ื˜. ื”ืคื•ื ืงืฆื™ื” ืžืงื‘ืœืช ืืช ื›ืœ ื”ืžื™ื“ืข ืžื”ื˜ื•ืคืก ืื•ื˜ื•ืžื˜ื™ืช ื“ืจืš ื”ืคืจื™ื™ืžื•ื•ืจืง ื•ื›ืš ืœื ืฆืจื™ืš ืœื—ื‘ืจ ื‘ื™ืŸ ืกื˜ื™ื™ื˜ ืœืžื™ื“ืข ืฉื™ืฉ ื‘ืงืœื˜ื™ื. ื”ืงื•ื“ ื“ื•ืจืฉ ืืช ื’ื™ืจืกื” 18.3 ืฉืœ ืจื™ืืงื˜ ืฉืขื“ื™ื™ืŸ ืœื ื™ืฆืื”, ืื‘ืœ ืืคืฉืจ ืœืจืื•ืช ื’ื™ืจืกื” ืขื•ื‘ื“ืช ืฉืœื• ืขื ื’ื™ืจืกืช ื”ืคื™ืชื•ื— ืฉืœื”ื ื›ืืŸ: https://codesandbox.io/s/vibrant-glade-dhrfz7?file=/src/App.js. ืœืžืจื•ืช ืฉื–ื” ื ืจืื” ืคื™ืฆ'ืจ ืงืฆืช ืžื™ื•ืชืจ, ืื ื™ ื—ื•ืฉื‘ ืฉืžื”ืจ ืžืื•ื“ ื”ื•ื ื™ื”ืคื•ืš ืœืคื™ื ื•ืง ืงื˜ืŸ ืฉื›ื•ืœื ืžืฉืชืžืฉื™ื ื‘ื• - ื’ื ื‘ื™ื™ืฉื•ืžื™ื ืงื˜ื ื™ื ื•ื’ื ื‘ืฉื™ืœื•ื‘ ืขื ืจื™ื“ืืงืก ืื• ืคืจื™ื™ืžื•ื•ืจืงื™ื ื’ื“ื•ืœื™ื ื™ื•ืชืจ, ื›ื™ ื”ื•ื ืคืฉื•ื˜ ื—ื•ืกืš ื—ืœืง ืžื” Boilerplate ืฉื›ื•ืœื ื• ื›ืชื‘ื ื• ื›ืœ ื”ื–ืžืŸ.

ToCode
1 420
# ื˜ื™ืค ืงื™ื“ื•ื“ ื ื›ื•ืŸ - ื•ืื™ืš ื–ื” ื ืจืื” ื›ืฉื–ื” ื ื›ืฉืœ? ืจื•ื‘ ื”ืžืชื›ื ืชื™ื ืœื ื‘ื˜ื•ื—ื™ื ืฉื”ืงื•ื“ ืื™ ืคืขื ื™ืขื‘ื•ื“. ืœื ื‘ื˜ื•ื—ื™ื ืฉืืคืฉืจ ื‘ื›ืœืœ ืœื›ืชื•ื‘ ื’ื™ืจืกื” ืฉืขื•ื‘ื“ืช ืœืžืฉื™ืžื” ืื™ืชื” ื”ื ืžืชืžื•ื“ื“ื™ื ื•ืœื›ืŸ ื”ื ืžืžื”ืจื™ื ืœื›ืชื•ื‘ ื’ื™ืจืกื” ืฉืขื•ื‘ื“ืช, ืœื ืžืฉื ื” ื›ืžื” ืžื™ื ื™ืžืœื™ืกื˜ื™ืช. ืžืคืชื—ื•ืช ื”ืฆืคื ื”? ื‘ื™ื ืชื™ื™ื ื ืฉื™ื ืื•ืชื ื‘ืงื•ื“ ืื—ืจื™ ืฉื™ืขื‘ื•ื“ ื ืžืฆื ืžื” ืœืขืฉื•ืช ืื™ืชื. ื›ืชื•ื‘ื•ืช ืฉืœ ืฉืจืชื™ื? ืชื›ืชื•ื‘ Hard Coded ื‘ื™ื ืชื™ื™ื ืื—ืจื™ ืฉื™ืขื‘ื•ื“ ื ื‘ื ื” ืžืกืš ื”ื’ื“ืจื•ืช ืžืกื•ื“ืจ. ื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช? ื”ืฆื—ืงืช ืื•ืชื. ื‘ื•ื ื ืจืื” ืฉื” flow ื”ืชืงื™ืŸ ืขื•ื‘ื“ ืœื ืฆืจื™ืš ืœืขื‘ื•ื“ ืกืชื. ื”ื‘ืขื™ื” ืฉืื—ืจื™ ืฉื™ืฉ flow ืžื™ื ื™ืžืœื™ ืฉืขื•ื‘ื“ ื”ื ื›ืœ ื›ืš ืฉืžื—ื™ื ืฉืžืฉื”ื• ืขื•ื‘ื“ ืฉื™ืฉืจ ืจืฆื™ื ืœื”ืจืื•ืช ืœื‘ื•ืก, ืžืงื‘ืœื™ื ืžื‘ื•ืœ ืฉืœ ืคื™ื“ื‘ืงื™ื ื•ืœืขื•ืœื ืœื ื™ื”ื™ื” ืœื”ื ื–ืžืŸ ืœื”ื•ืกื™ืฃ ืืช ื”ื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช. ืœื›ืŸ ืื—ื“ ื”ื˜ื™ืคื™ื ื”ื›ื™ ืงืœื™ื ืœืงื™ื“ื•ื“ ื ื›ื•ืŸ ื™ื•ืชืจ ื”ื•ื ืœื˜ืคืœ ื‘ืฉื’ื™ืื•ืช ื‘ื–ืžืŸ ืฉื›ื•ืชื‘ื™ื ืืช ื”ืงื•ื“. ืื ื›ืชื‘ืชื™ ื‘ืคื™ื™ืชื•ืŸ ืืช ื”ืฉื•ืจื”:
with open('/etc/passwd') as f:
    ...
ืžืžืฉ ื‘ืื•ืชื• ืจื’ืข ืื ื™ ืืฉืืœ - ื•ืื™ืš ื–ื” ื™ื›ื•ืœ ืœื”ื™ืฉื‘ืจ? ืžื” ืื ืื™ืŸ ืœื™ ื”ืจืฉืื•ืช ืœืงื•ื‘ืฅ? ืžื” open ื™ืขืฉื”? ื•ืžื” ืื ื”ืงื•ื‘ืฅ ืœื ืงื™ื™ื, ืžื” open ื™ืขืฉื”? ื•ืžื” ืื ื”ื ืชื™ื‘ ื”ื•ื ื‘ื’ืœืœ ื ืชื™ื‘ ืœืชื™ืงื™ื”, ืžื” open ื™ืขืฉื”? ื•ื”ืฆืขื“ ื”ื‘ื ื“ื•ืจืฉ ืฉื™ืœื•ื‘ ืฉืœ ืกื‘ืœื ื•ืช ื•ื‘ื™ื˜ื—ื•ืŸ ืขืฆืžื™, ืื‘ืœ ืœื’ืžืจื™ ืฉื•ื•ื” ืืช ื–ื” - ื‘ืžืงื•ื ืœื›ืชื•ื‘ ืงื•ื“ื ื›ืœ ืืช ืชื•ื›ืŸ ื”ืœื•ืœืื”, ืื ื™ ืžืชื—ื™ืœ ืžื”ืงื•ื“ ืฉืžื˜ืคืœ ื‘ื›ืœ ื”ื“ืจื›ื™ื ื‘ื”ืŸ ื”ืฉื•ืจื” ืฉืœื™ ื™ื›ื•ืœื” ืœื”ื™ืฉื‘ืจ ื•ืžื•ื•ื“ื ืฉื‘ื›ืœ ื“ืจืš ื”ืชื•ื›ื ื™ืช ืชืชื ื”ื’ ื›ืžื• ืฉืื ื™ ืจื•ืฆื” ืฉืชืชื ื”ื’. ืจืง ืื—ืจื™ ืฉืกื™ื™ืžืชื™ ืœื˜ืคืœ ื‘ื›ื™ืฉืœื•ื ื•ืช ืื ื™ ืžืžืฉื™ืš ืœื˜ืคืœ ื‘ืžืฆื‘ ื”ืชืงื™ืŸ. ื•ื›ืŸ ื”ื˜ื™ืค ื”ื–ื” ืœื ืจืœื•ื•ื ื˜ื™ ื›ืฉืขื•ืฉื™ื ืคืจื•ื˜ื•ื˜ื™ื™ืค ืœืžืขืจื›ื•ืช, ืื‘ืœ ืฆืจื™ืš ืœืฉื™ื ืœื‘ ืฉืื ื”ืคืจื•ื˜ื•ื˜ื™ื™ืคื™ื ืฉืœื›ื ื ื•ื˜ื™ื "ืœื”ืคื•ืš" ืœื’ื™ืจืกื” ื”ืืžื™ืชื™ืช, ืื•ืœื™ ืฉื•ื•ื” ืœื‘ื ื•ืช ืชื”ืœื™ืš ืคื™ืชื•ื— ื˜ื•ื‘ ื™ื•ืชืจ ื’ื ืขื‘ื•ืจื.