uz
Feedback
ToCode

ToCode

Kanalga Telegramโ€™da oโ€˜tish

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

Ko'proq ko'rsatish
1 419
Obunachilar
Ma'lumot yo'q24 soatlar
Ma'lumot yo'q7 kunlar
Ma'lumot yo'q30 kunlar
Postlar arxiv
ToCode
1 419
# ืื ื™ ืœื ืžืืžื™ืŸ ืฉืฉื•ื‘ ื˜ืขื™ืชื™ ื‘ useEffect ื™ื•ื ืื—ื“ ืื ื™ ืืคืชื— ืžื•ื–ื™ืื•ืŸ ืœื›ืœ ื”ื˜ืขื•ื™ื•ืช ื”ืžื•ื–ืจื•ืช ืฉืื ื™ ืขื•ืฉื” ืขื useEffect. ื‘ื™ื ืชื™ื™ื ืืชื ืžื•ื–ืžื ื™ื ืœื”ืฆื™ืฅ ื‘ืงื•ื“ ื”ืฉื‘ื•ืจ ืฉืื ื™ ื›ืชื‘ืชื™ ื•ืœืจืื•ืช ื›ืžื” ื–ืžืŸ ืœื•ืงื— ืœื›ื ืœืžืฆื•ื ืืช ื”ื‘ืขื™ื”. ื”ืงื•ื“ ืžืฉืชืžืฉ ื‘ ResizeObserver ื›ื“ื™ ืœื”ืจื™ืฅ ืงื•ื“ ื›ืœ ืคืขื ืฉื”ื’ื•ื“ืœ ืฉืœ ืืœืžื ื˜ ืžืกื•ื™ื ืฉื”ื•ื ืžืกืชื›ืœ ืขืœื™ื• ืžืฉืชื ื”:
import React, { useEffect } from 'react';

// trackedRef is a reference to a DOM element
export default function ResizeHandler({ trackedRef }) {
  useEffect(() => {
    const resizeObserver = new ResizeObserver(() => {
      const height = trackedRef.current.scrollHeight;
      console.log(`Your new height is: ${height}`);
    });
    resizeObserver.observe(trackedRef.current);

    return function cancel() {
      resizeObserver.disconnect();
    }
  }, [trackedRef]);

  return <></>;
}
ืจื•ืื™ื ืืช ื”ื‘ืื’? ืžื•ื–ืžื ื™ื ืœืฉืชืฃ ื‘ืชื’ื•ื‘ื•ืช ื•ืœื”ื™ื–ื”ืจ ืžืกื›ื™ื ื™ื ื—ื“ื•ืช. (ื .ื‘. ืžื›ืœ ื”ืคื•ื ืงืฆื™ื•ืช ืฉืœ ืจื™ืืงื˜, useEffect ื”ื™ืชื” ื‘ืฉื‘ื™ืœื™ ืื”ื‘ื” ืžืžื‘ื˜ ืจืืฉื•ืŸ. ื”ื’ืขืชื™ ืืœื™ื” ืขื ื”ื˜ืจืื•ืžื” ืฉืœ ื”ื›ืคื™ืœื•ืช ื‘ื™ืŸ componentDidMount ื• componentDidUpdate ื•ื—ืฉื‘ืชื™ ืฉื”ื ื” ื™ืฉ ืคื™ืชืจื•ืŸ ืœื›ืœ ื”ืฆืจื•ืช ืฉืœื™ ื‘ืžืงื•ื ืื—ื“. ื‘ืคื•ืขืœ ื—ื•ืกืจ ืชืฉื•ืžืช ืœื‘ ื›ืžื• ื‘ื“ื•ื’ืžื” ื›ืืŸ ื’ื•ืจื ืœื™ ืœื™ื™ืฆืจ ืื™ื ืกื•ืฃ ื‘ืื’ื™ื ื™ืฆื™ืจืชื™ื™ื ื‘ืขื‘ื•ื“ื” ืื™ืชื”. ื‘ืžืงืจื” ื”ื–ื” ืœืžืจื•ืช ืฉื”ืฉืชืžืฉืชื™ ื‘ eslint ื•ืœืžืจื•ืช ืฉ eslint ื›ื•ืœืœ ื›ืœืœ ืกืคืฆื™ืคื™ ืœื”ืชืžื•ื“ื“ื•ืช ืขื ื”ื‘ืื’ ื‘ืงื•ื“ ื”ืžื•ื“ื‘ืง ื”ื•ื ืขื“ื™ื™ืŸ ื”ืชืขืœื ืžื”ื˜ืขื•ืช ื•ืœื ื”ื–ื”ื™ืจ. ืื™ืŸ ืœื™ ืคื” ื”ืžืœืฆื•ืช ืงืกื ื—ื•ืฅ ืžืœื”ื™ื•ืช ืžืื•ื“ ื–ื”ื™ืจื™ื ื‘ืขื‘ื•ื“ื” ืขื useEffect, ืœื›ืชื•ื‘ ืืคืงื˜ื™ื ืงืฆืจื™ื ื•ืœื ื™ื•ืชืจ ืžื“ื™ ืžื”ื ื•ืœืงื•ื•ืช ืฉื‘ืื™ื˜ืจืฆื™ื” ื”ื‘ืื” ืฉืœ ืจื™ืืงื˜ ื“ืŸ ืื‘ืจืžื•ื‘ ื™ื‘ื•ื ืขื ืžื ื’ื ื•ืŸ ื™ื•ืชืจ ื™ื“ื™ื“ื•ืชื™).

ToCode
1 419
# ื”ื–ืžื ื” ืœื•ื•ื‘ื™ื ืจ: ื ื™ื”ื•ืœ ืžืฉืชืžืฉื™ื ืขื auth0 ืชืงืŸ OAuth ื”ื™ื” ืื—ืช ื”ืžื”ืคื›ื•ืช ื”ื’ื“ื•ืœื•ืช ืฉืœ ื”ืื™ื ื˜ืจื ื˜, ื”ื•ื ืื™ืคืฉืจ ืœื‘ื ื•ืช ืืช ืžื ื’ื ื•ื ื™ ื”ื”ื–ื“ื”ื•ืช ืฉื›ื•ืœื ื• ืžืฉืชืžืฉื™ื ื‘ื”ื. ืœืฆืขืจื• ืฉืœ OAuth ื”ื•ื ื’ื ืžืกืคื™ืง ืžืกื•ื‘ืš ื‘ืฉื‘ื™ืœ ืฉืžืชื›ื ืชื™ื ืœื ื™ืจืฆื• ืœืœืžื•ื“ ืื•ืชื•, ื•ื›ืš ื™ืฆื ืฉื›ืฉืื ื—ื ื• ื›ืŸ ืฆืจื™ื›ื™ื ืœืžืžืฉ ืžื ื’ื ื•ืŸ ื”ื–ื“ื”ื•ืช ืื ื—ื ื• ืžื—ืคืฉื™ื ืื™ื–ื” Tutorial ืคืฉื•ื˜ ื•ื”ืจื‘ื” ืคืขืžื™ื ื‘ื•ื ื™ื ืœืคื™ ื”ื”ื•ืจืื•ืช ื“ื‘ืจ ืฉืœื ืžืชืื™ื ืœื ื• ืื• ืขื ื˜ืขื•ื™ื•ืช. ื”ืฉื‘ื•ืข ืื ื—ื ื• ื”ื•ืœื›ื™ื ืœืชืงืŸ ืืช ื–ื”. ื‘ื™ื•ื ื—ืžื™ืฉื™ ื”ืงืจื•ื‘ ืืขื‘ื™ืจ ื›ืืŸ ื•ื•ื‘ื™ื ืจ ืฉืœ ืฉืขื” ืขืœ OAuth ืฉื™ื›ืกื” ื’ื ืืช ื”ืชื™ืื•ืจื™ื” ื•ื’ื ื‘ื ื™ื” ืฉืœ ืžืขืจื›ืช ืฉืจืช/ืœืงื•ื— ื”ืžืฉืชืžืฉืช ื‘ OAuth ื›ื“ื™ ืœืืคืฉืจ ืœืžืฉืชืžืฉื™ื ืœื’ืฉืช ืœ API ื‘ืฆื•ืจื” ืžืื•ื‘ื˜ื—ืช. ื‘ื•ื•ื‘ื™ื ืจ ื ืจืื”: 1. ืžื” ื–ื” OAuth, ืžื” ื–ื” OpenID Connect, ื•ืชื›ืœืณืก ืื™ืš ื–ื” ืขื•ื‘ื“. 2. ื ื›ื™ืจ ืืช Auth0, ืฉื”ื•ื ืžืขืจื›ืช ืขื ืŸ ืฉืžื˜ืคืœืช ื‘ืจื•ื‘ ื”ื—ืœืงื™ื ื”ืงืฉื™ื ื‘ืžื™ืžื•ืฉ ืžื ื’ื ื•ืŸ ื”ื–ื“ื”ื•ืช ื‘ OAuth. 3. ื ื‘ื ื” ื‘ืขื–ืจืช Auth0 ืฉืจืช API ืฉืจืง ืžืฉืชืžืฉื™ื ืจืฉื•ืžื™ื ื™ื›ื•ืœื™ื ืœืคื ื•ืช ืืœื™ื•. 4. ื ื‘ื ื” ืœืงื•ื— React ืฉื™ืืคืฉืจ ืœืžืฉืชืžืฉื™ื "ืœื”ืชื—ื‘ืจ" ืœืžืขืจื›ืช ื•ืœื‘ืฆืข ืคืขื•ืœื•ืช ื‘ืฉืจืช ื” API. ื‘ื“ืจืš ื ื“ื‘ืจ ืขืœ JWT, Access Tokens, ID Tokens, Refresh Tokens, ืขืœ ื ื™ื”ื•ืœ Session ื‘ืขื–ืจืช Cookies ืื• Local Storage, ื•ื›ืœ ืฉืืœื” ืื—ืจืช ืฉืชื”ื™ื” ืœื›ื ื‘ื ื•ืฉื ื”ื–ื“ื”ื•ืช. ื”ื•ื•ื‘ื™ื ืจ ื™ืขืจืš ื‘ื–ื•ื ื‘ื™ื•ื ื—ืžื™ืฉื™ ื”ืงืจื•ื‘ ื” 2/6 ื‘ืฉืขื” ืขืฉืจ ื‘ื‘ื•ืงืจ. ืœืคืจื˜ื™ื ื•ื”ืจืฉืžื” ื‘ื—ื™ื ื ื”ื›ื ืกื• ืœื“ืฃ ื”ื•ื•ื‘ื™ื ืจ ื‘ืงื™ืฉื•ืจ: https://www.tocode.co.il/workshops/114

ToCode
1 419
ืืœืžื ื˜ Layout ื”ื•ื ื‘ืกืš ื”ื›ืœ ืงื•ืžืคื•ื ื ื˜ืช ืจื™ืืงื˜ ืฉืžื•ืฉื›ืช ืืช ื”ืžื™ื“ืข ื•ืžืขื‘ื™ืจื” ืื•ืชื• ืœ Homepage ืื• About ื‘ื”ืชืืžื”. ืจืง ื‘ืฉื‘ื™ืœ ื”ื”ื‘ื ื” ื”ื•ืกืคืชื™ ื›ื•ืชืจืช ืžืฉื•ืชืคืช ืœื›ืœ ื”ื“ืคื™ื ื•ื”ื“ืคืกื” ืฉืœ ื”ื ืชื™ื‘ ืฉืื ื—ื ื• ื›ืจื’ืข ืžื‘ืงืจื™ื ื‘ื•. ื–ื” ื”ืงื•ื“ ืฉืœ Layout:
function Layout() {
  const location = useLocation();
  const url = useHref(location);
  const { data, error } = useSWR(url, fetcher)

  if (error) {
    console.log(error);
    return <p>Error: {JSON.stringify(error)}</p>
  }

  return (
    <div>
      <h1>My App</h1>
      <p>Visiting: {url}</p>
      {data && <Outlet context={data} />}
    </div>
  );
}
ื”ื—ื‘ืจ ื”ืื—ืจื•ืŸ ื‘ืฆื“ ืฉืœ ื” Layout ื”ื•ื ื”ืคื•ื ืงืฆื™ื” fetcher ืฉื‘ื•ื“ืงืช ืื ื” url ืžืชืื™ื ืœืžื™ื“ืข ืฉืžื•ื˜ืžืข ื‘ืขืžื•ื“, ื›ืœื•ืžืจ ืื ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ืขื‘ื™ืจ ืืช ื”ืžื™ื“ืข ืžื”ื“ืฃ ืฉื”ืจื’ืข ื ื˜ืขืŸ. ืื ื” url ื–ื”ื” ืื– ืืคืฉืจ ืœื”ื—ื–ื™ืจ ืืช ื”ืžื™ื“ืข ืฉื‘ื“ืฃ, ื•ืื ื”ื•ื ืฉื•ื ื” ื–ื” ืื•ืžืจ ืฉืื ื—ื ื• ื‘ืžืขื‘ืจ ืขืžื•ื“ ื•ืื– ืฆืจื™ืš ืœื˜ืขื•ืŸ ื‘ืชื•ืจ JSON ืืช ื”ืžืฉืชื ื™ื ืžื”ื ืชื™ื‘ ื”ื—ื“ืฉ. ื–ื” ื”ืงื•ื“:
const fetcher = async (url) => {
  const pageData = document.querySelector(`#page-data[data-url="${url}"]`);
  if (pageData) {
    console.log(`Reading data from page`);
    return JSON.parse(pageData.innerHTML);
  } else {
    const res = await fetch(url, { headers: { accept: 'application/json' } })
    return await res.json();
  }
}
ืขื›ืฉื™ื• ืื ื™ ื™ื›ื•ืœ ืœื”ืžืฉื™ืš ืœื“ืคื™ื ืขืฆืžื ื•ืฉื ืœืžืฉื•ืš ืืช ื”ืžื™ื“ืข ื•ืœื”ืฉืชืžืฉ ื‘ื•. ื”ืžืฉื™ื›ื” ืžืฉืชืžืฉืช ื‘ืคื•ื ืงืฆื™ื” ืฉืœ React Router ืฉื ืงืจืืช useOutletContext ื•ื”ืงื•ื“ (ืœื“ื•ื’ืžื” ืฉืœ ื“ืฃ ื”ื‘ื™ืช) ื ืจืื” ื›ืš:
import React, { useState } from 'react';
import { Link, useOutletContext } from "react-router-dom";

export default function Homepage() {
  const [name, setName] = useState('');
  const { page } = useOutletContext();

  return (
    <div>
      <h2>Page Name From Rails: {page}</h2>
      <label>
        Please type your name:
        <input type="text" value={name} onChange={(e) => setName(e.currentTarget.value)} />
      </label>
      {name !== '' && <p>Hello! {name}</p>}
      <Link to="/about/index">About Us</Link> 

    </div>
  );
}
## ืกื™ื›ื•ื ืœืžืจื•ืช ืฉืœื ื”ืฉืชืžืฉื ื• ื‘ืžื ื’ื ื•ื ื™ื ื”ืžื•ื‘ื ื™ื ืฉืœ ืจื™ื™ืœืก, ื”ืชื•ืฆืื” ื”ื™ื ืงื•ื“ ืฉื™ืจืื” ืžื•ื›ืจ ื‘ืฆื“ ื”ืฉืจืช ืœืžืชื›ื ืชื™ื ืจื™ื™ืœืก ื•ื‘ืฆื“ ื”ืœืงื•ื— ืœืžืชื›ื ืชื™ ืจื™ืืงื˜. ื‘ืฆื“ ื”ืฉืจืช ืงื•ื ื˜ืจื•ืœืจ ืคืฉื•ื˜ ืฆืจื™ืš ืœืืชื—ืœ ืžืฉืชื ื” ื•ืœืงืจื•ื ืœืคื•ื ืงืฆื™ื” respond_with:
class HomeController < ApplicationController
  def index
    @page = { page: 'Home Page' }
    respond_with(@page)
  end
end
ื›ืฉืื•ืœื™ ื”ื“ื‘ืจ ื”ื™ื—ื™ื“ ืฉืžื•ื–ืจ ื›ืืŸ ื–ื” ืฉื”ืฉื ื—ื™ื™ื‘ ืœื”ื™ื•ืช @page ื›ื“ื™ ืœื”ืชืื™ื ืœืงื•ื“ ืฉื›ืชื‘ื ื• ื‘ layout. ื‘ืฆื“ ื”ืœืงื•ื— ืื ื™ ืžืฉืชืžืฉ ื‘ืคื•ื ืงืฆื™ื” useOutletContext ื›ื“ื™ ืœืžืฉื•ืš ืืช ื”ืžืฉืชื ื” page, ืฉื™ื›ื•ืœ ืœื”ื™ื•ืช ื’ื ืื•ื‘ื™ืงื˜ JSON ืžื•ืจื›ื‘ ืฉืžื›ื™ืœ ืชื•ืฆืื” ืฉืœ ืฉืื™ืœืชื” ืื• ืฉืื™ืœืชื•ืช ืžืกื•ื‘ื›ื•ืช, ื•ืžืฉืชืžืฉ ื‘ื• ื‘ืงื•ืžืคื•ื ื ื˜ื”:
import React, { useState } from 'react';
import { Link, useOutletContext } from "react-router-dom";

export default function Homepage() {
  const [name, setName] = useState('');
  const { page } = useOutletContext();

  return (
    <div>
      <h2>Page Name From Rails: {page}</h2>
      <label>
        Please type your name:
        <input type="text" value={name} onChange={(e) => setName(e.currentTarget.value)} />
      </label>
      {name !== '' && <p>Hello! {name}</p>}
      <Link to="/about/index">About Us</Link> 

    </div>
  );
}
ืืช ื”ืงื•ื“ ื”ืžืœื ืชื•ื›ืœื• ืœืžืฆื•ื ื‘ืจื™ืคื•: https://github.com/ynonp/react-rails-vite-demo

ToCode
1 419
# ืžื“ืจื™ืš: ื™ืฆื™ืจืช ืืคืœื™ืงืฆื™ื™ืช React ื‘ืชื•ืš ืฉืจืช Rails 7 - ื—ืœืง 2 - ื”ืขื‘ืจืช ืžืฉืชื ื™ื ืคื•ืกื˜ ื–ื” ื”ื•ื ื—ืœืง ืฉื ื™ ืฉืœ ืžื“ืจื™ืš ื”ืงืžืช ื™ื™ืฉื•ื React ื• Rails ื‘ Rails 7. ืื ืคืกืคืกืชื ื”ื—ืœืง ื”ืจืืฉื•ืŸ ื–ืžื™ืŸ ื‘ืงื™ืฉื•ืจ: https://www.tocode.co.il/blog/2022-05-react-rails-7-vite-rails ื‘ื—ืœืง ื–ื” ื ืจืื” ื“ืจืš ืื—ืช ืœื”ืขื‘ื™ืจ ืžืฉืชื ื™ื ื‘ื™ืŸ ืฉืจืช ื”ืจื™ื™ืœืก ืœื™ื™ืฉื•ื ื”ืจื™ืืงื˜. ## ื”ื‘ืขื™ื” ืขื ืžืฉืชื ื™ื ื‘ื—ืœืง ื”ืงื•ื“ื ืฉืœ ื”ืžื“ืจื™ืš ื”ืจืื™ืชื™ ืื™ืš ืœื‘ื ื•ืช ืฉืจืช ืจื™ื™ืœืก ืฉืžื’ื™ืฉ ืœืœืงื•ื— ืืคืœื™ืงืฆื™ื™ืช ืจื™ืืงื˜. ืžื” ืฉืœื ื“ื™ื‘ืจืชื™ ืขืœื™ื• ื–ื” ื”ืงืฉืจ ื‘ื™ืŸ ืฉื ื™ ื”ื—ืœืงื™ื - ื•ื‘ืคืจื˜ ืื™ืš ืื ื™ ืžืขื‘ื™ืจ ืžื™ื“ืข ืž Rails Controller ืœื“ืฃ ื‘ืจื™ืืงื˜ ืฉืžืชืื™ื ืœื•. ื‘ืชื•ื›ื ื™ืช ื”ื“ื•ื’ืžื” ื”ื™ื• ืœื ื• ืฉื ื™ Rails Controllers, ืื—ื“ ืขื‘ื•ืจ ืขืžื•ื“ ื”ื‘ื™ืช ื•ื”ืฉื ื™ ืขื‘ื•ืจ ืขืžื•ื“ ืื•ื“ื•ืช, ื•ืฉื ื™ื”ื ืœื ื”ืจื™ืฆื• ืงื•ื“ ื•ืœื›ืŸ ื”ื—ื™ื™ื ื”ื™ื• ืงืœื™ื. ืœืจื™ื™ืœืก ื™ืฉ ืžื ื’ื ื•ืŸ ื“ื™ ื˜ื•ื‘ ืœื”ืขื‘ืจืช ืžื™ื“ืข ืž Controller ืœ View ืฉืžืชืื™ื ืœื•, ื•ืืœื” ื”ื ืžืฉืชื ื™ ื” @ ืฉืœ ื”ืงื•ื ื˜ืจื•ืœืจ. ื›ืœื•ืžืจ ืื ื™ ื™ื›ื•ืœ ืœื›ืชื•ื‘ ื‘ืงื•ื“ ืฉืœ ืงื•ื ื˜ืจื•ืœืจ:
def index
    @page_name = "Homepage"
end
ื•ืื—ืจื™ ื–ื” ื‘ View ืื ื™ ื™ื›ื•ืœ ืคืฉื•ื˜ ืœื”ืฉืชืžืฉ ื‘ @page_name ื‘ืชื•ืš ื” HTML ืฉืœ ื”ืขืžื•ื“:
<h1><%= @page_name %></h1>
ื”ื‘ืขื™ื” ืฉืื ื—ื ื• ื›ื‘ืจ ืœื ื‘ืงื ื–ืก - ืื• ื™ื•ืชืจ ื ื›ื•ืŸ ืœื ืžืฉืชืžืฉื™ื ื‘ Views ืฉืœ Rails. ืžื” ืฉื™ื•ืชืจ ื’ืจื•ืข ื”ื•ื ืฉื›ืœ ืžื ื’ื ื•ืŸ ืžืขื‘ืจื™ ื”ื“ืคื™ื ืฉืœื ื• ืžืฉืชืžืฉ ื‘ React Router ื•ืœื ื‘ Turbolinks, ื•ืœื›ืŸ ืืคื™ืœื• ืื ื”ื™ื™ื ื• ืžืฆืœื™ื—ื™ื ืœื’ืจื•ื ืœื“ืฃ ื”ืจืืฉื•ืŸ ืœื”ืฆื™ื’ ืžื™ื“ืข ื“ืจืš ื” Views (ืœืžืฉืœ ืขื ื’'ื ื›ืžื• Gon), ืื—ืจื™ ืžืขื‘ืจ ืขืžื•ื“ ืœื ื”ื™ื” ืฉื•ื ื“ื‘ืจ ืฉื’ื•ืจื ืœืขืžื•ื“ ื”ื—ื“ืฉ ืœื”ืฆื™ื’ ืืช ื”ืžื™ื“ืข ื”ืžืขื•ื“ื›ืŸ. ืชืฉืžื—ื• ืœืฉืžื•ืข ืฉื‘ื’ืœืœ ื”ื’ืžื™ืฉื•ืช ืฉืœ ืจื™ื™ืœืก ื•ืจื™ืืงื˜ ืžืื•ื“ ืงืœ ืœื‘ื ื•ืช ื‘ืขืฆืžื ื• ืžื ื’ื ื•ืŸ ืฉื™ืจืื” ืžืื•ื“ ื“ื•ืžื” ืœืžื ื’ื ื•ืŸ ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ืื‘ืœ ื™ืขื‘ื•ื“ ื‘ืจื™ืืงื˜. ## ืคื™ืชืจื•ืŸ ื‘ืืžืฆืขื•ืช REST API ื”ืคื™ืชืจื•ืŸ ืฉื ื‘ื ื” ื™ืชื‘ืกืก ืขืœ ื’'ื ืฉื ืงืจื responders. ื’'ื ื–ื” ืžืืคืฉืจ ืœื”ื’ื“ื™ืจ ืฉื›ืœ ืงื•ื ื˜ืจื•ืœืจ ื™ื•ื›ืœ ืœื”ื’ื™ื‘ ืœื›ืœ ืžื™ื ื™ ืกื•ื’ื™ื ืฉืœ ื‘ืงืฉื•ืช - ื‘ืžืงืจื” ืฉืœื ื• ื ื’ื“ื™ืจ ืฉืื ืžื‘ืงืฉื™ื ืžืงื•ื ื˜ืจื•ืœืจ ื“ืฃ HTML ื”ื•ื ื™ืฉืœื— ื“ืฃ ืจื’ื™ืœ ื›ืžื• ืฉืขืฉื” ืขื“ ืขื›ืฉื™ื•, ื•ื™ืฉืชื•ืœ ืืช ื”ืžืฉืชื ื™ื ื‘ืชื•ืš ืืœืžื ื˜ ื ืกืชืจ ื‘ื“ืฃ ื”ื–ื”. ืื‘ืœ, ืื ืžื‘ืงืฉื™ื ืžืื•ืชื• ืงื•ื ื˜ืจื•ืœืจ ืœืงื‘ืœ JSON, ืื– ื”ื•ื ื™ืฉืœื— ืจืง ืืช ื”ืžืฉืชื ื™ื ื‘ืชื•ืจ JSON. ืชื—ื™ืœื” ืื ื™ ืžืชืงื™ืŸ ืืช ื”ื’'ื ืขื:
$ bundle add responders
ืขื›ืฉื™ื• ืื ื™ ื”ื•ืœืš ืœ application_controller.rb ื•ืžื’ื“ื™ืจ ืœื• ืฉื”ื•ื ื•ื›ืœ ืงื•ื ื˜ืจื•ืœืจ ืฉื™ื•ืจืฉ ืžืžื ื• ื™ืกื›ื™ื ืœืขื ื•ืช ืœื‘ืงืฉื•ืช ืœ html ื•ื’ื ืœื‘ืงืฉื•ืช ืœ json:
class ApplicationController < ActionController::Base
  respond_to :html, :json
end
ื ืžืฉื™ืš ืœ home_controller.rb ื•ื ื’ื“ื™ืจ ืฉื ืžืฉืชื ื”, ืื ื™ ืืงืจื ืœื• @page, ืฉื™ื›ื™ืœ ืื•ื‘ื™ืงื˜ ืขื ืžืคืชื— ื‘ืฉื page ืฉื”ืชื•ื›ืŸ ืฉืœื• ื”ื•ื ื›ื•ืชืจืช ื”ืขืžื•ื“:
class HomeController < ApplicationController
  def index
    @page = { page: 'Home Page' }
    respond_with(@page)
  end
end
ืื•ืชื• ื“ื‘ืจ ืื ื™ ื›ื•ืชื‘ ื‘ about_controller.rb ืจืง ืขื ื›ื•ืชืจืช ืขืžื•ื“ ืฉื•ื ื”:
class AboutController < ApplicationController
  def index
    @page = { page: 'About Page' }
    respond_with(@page)
  end
end
ื”ืคืงื•ื“ื” respond_with ืžื’ื™ืขื” ืžื”ื’'ื responder ื•ื”ื™ื ื”ืžืงื•ืจ ืœืจื•ื‘ ื”ืงืกื ื›ืืŸ. ื”ื™ื ืžืชืื™ืžื” ืœืคืงื•ื“ืช ื” respond_to ืฉื›ืชื‘ื ื• ื‘ืจืืฉ ื”ืงื•ื ื˜ืจื•ืœืจ ื”ืจืืฉื™. ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ respond_with ื™ื•ื“ืขืช ืœืงื—ืช ืืช ื”ืžืฉืชื ื” ืฉื ืชื ื• ืœื” ื•ืœื”ืคื•ืš ืื•ืชื• ืœ JSON ืื ืžื™ืฉื”ื• ืžื‘ืงืฉ JSON. ื‘ืฉื‘ื™ืœ ืœืฉืชื•ืœ ืืช ื”ืžืฉืชื ื” ื”ื–ื” ื‘ HTML ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื›ืชื•ื‘ ืงืฆืช ืงื•ื“. ื ืœืš ืœ app/views/layout/application.html.erb ื•ืฉื ืžืชื—ืช ืœ body ืื ื™ ืžื•ืกื™ืฃ ืืช ื”ื‘ืœื•ืง ื”ื‘ื:
<% if defined?(@page) %>
    <script type="text/json" id="page-data" data-url="<%= request.fullpath %>">
    <%= raw @page.to_json %>
    </script>
<% end %>
ืขื›ืฉื™ื• ื‘ื›ืœ ื˜ืขื™ื ืช ืขืžื•ื“ ืจื™ื™ืœืก ื™ืฉืชื•ืœ ื‘ืชื•ื›ื• ืืœืžื ื˜ script ืขื ืชื•ื›ืŸ ื”ืžืฉืชื ื” @page, ื•ื‘ื›ืœ ืžืขื‘ืจ ืขืžื•ื“ ืจื™ื™ืœืก ื™ืฉืœื— ืืช ืชื•ื›ืŸ ื”ืžืฉืชื ื” @page ื‘ืชื•ืจ ืื•ื‘ื™ืงื˜ JSON ืœืœืงื•ื—. ## ืชื™ืงื•ืŸ ืฆื“ ืœืงื•ื— ื‘ืฆื“ ืฉืœ ืจื™ืืงื˜ ืื ื™ ืฆืจื™ืš ืœืžืฉื•ืš ืืช ื”ืžื™ื“ืข ื•ืœื”ืขื‘ื™ืจ ืื•ืชื• ืœื“ืคื™ื. ื“ืจืš ืงืœื” ืœืขืฉื•ืช ืืช ื–ื” ื”ื™ื ืœืจื ื“ืจ ืืœืžื ื˜ Layout ื›ืœืœื™ ืœื›ืœ ื”ื“ืคื™ื ืฉื™ื”ื™ื” ืื—ืจืื™ ืขืœ ืžืฉื™ื›ืช ื”ืžื™ื“ืข ืžื”ืฉืจืช ืื• ืžื”ืชื•ื›ืŸ ืฉื›ื‘ืจ ืžื•ื˜ืžืข ื‘ HTML, ื•ื™ืขื‘ื™ืจ ืื•ืชื• ืคื ื™ืžื” ืœืืœืžื ื˜ ืฉืžืชืื™ื ืœื“ืฃ ื”ื ื•ื›ื—ื™. ื‘ืฉื‘ื™ืœ ืœื”ื•ืกื™ืฃ ืืœืžื ื˜ Layout ืžืกื‘ื™ื‘ ืœืืœืžื ื˜ ื“ืฃ ื”ื‘ื™ืช ืื• ื“ืฃ ื”ืื•ื“ื•ืช ืื ื™ ืžืฉืชืžืฉ ื‘ืงื•ื“ ื”ื‘ื ื‘ืงื•ื‘ืฅ entrypoints/application.jsx:

function App() {
  return (
    <Router>
        <Routes>
          <Route element={<Layout />}>
            <Route path="/" element={<Homepage />} />
            <Route path="/about/index" element={<About />} />
          </Route>
        </Routes>
    </Router>
  );
}

ToCode
1 419
ื’ื grep ืขื•ื‘ื“ ืขืœ ืคืชืงื™ื ื•ืœื›ืŸ ืื ื™ ื™ื›ื•ืœ ืœืกื ืŸ ืจืง ืงื•ืžื™ื˜ื™ื ืฉืžื›ื™ืœื™ื ืืช ื”ื˜ืงืกื˜ All passed ื‘ืคืชืง ื”ื‘ื“ื™ืงื•ืช:
$ git log --notes=testing --oneline --grep "All passed"

4126289 added about page
Notes (testing):
    performed 10 tests. All passed
## ืฉืœื™ื—ืช ืคืชืงื™ื ืœืฉืจืช ืžืจื•ื—ืง ื‘ืขื‘ื•ื“ื” ืขื ืžืื’ืจ ืžืจื•ื—ืง ืื•ืœื™ ืœื ืชืฉืžื—ื• ืœืฉืžื•ืข ืฉื”ืคืชืงื™ื ืื™ื ื ื ืฉืœื—ื™ื ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ืœืžืื’ืจ ื‘ื›ืœ push ืฉืืชื ืžืคืขื™ืœื™ื. ื”ืคืงื•ื“ื” ื”ื‘ืื” ื“ื•ื—ืคืช ืืช ื”ืžืื’ืจ ื™ื—ื“ ืขื ื”ืคืชืงื™ื:
git push origin "refs/notes/*"
ื•ื’ื ื‘ืžืฉื™ื›ื” ืžืžืื’ืจ ืžืจื•ื—ืง ืœื ืชืงื‘ืœื• ืืช ื”ืคืชืงื™ื, ื•ื‘ืฉื‘ื™ืœ ืœืžืฉื•ืš ืื•ืชื ืชืฆื˜ืจื›ื• ืœื”ืคืขื™ืœ:
git fetch origin "refs/notes/*:refs/notes/*"
ืื ืžื•ื’ื“ืจ ืœืคืจื•ื™ืงื˜ ืฉืœื›ื ืฉืจืช ืžืจื•ื—ืง ื‘ืฉื origin, ื”ืคืงื•ื“ื•ืช ื”ื‘ืื•ืช ื™ื’ืจืžื• ืœื›ืœ ืคืขื•ืœืช push ื• fetch ืœื›ืœื•ืœ ื’ื ืืช ื”ืคืชืงื™ื
$ git config --add remote.origin.push '+refs/notes/*:refs/notes/*'

$ git config --add remote.origin.fetch '+refs/notes/*:refs/notes/*'

ToCode
1 419
# ืžื”ื Git Notes ื•ืื™ืš ื”ื ืขื•ื–ืจื™ื ืœื ื• ืœืขืฉื•ืช ืกื“ืจ ื‘ืžืื’ืจ ื’ื™ื˜ ื”ืคื™ืฆ'ืจ ืฉืœ git notes ืงื™ื™ื ื‘ื’ื™ื˜ ื›ื‘ืจ ืขืฉืจ ืฉื ื™ื ื‘ืขืจืš ืื‘ืœ ืžืขื˜ ืื ืฉื™ื ืžื›ื™ืจื™ื ืื•ืชื• ืื• ืžืฉืชืžืฉื™ื ื‘ื•. ื‘ืคื•ืกื˜ ื–ื” ื ืจืื” ืžื”ื notes ื•ืžื” ื”ืคืงื•ื“ื•ืช ื”ืžืจื›ื–ื™ื•ืช ืœืขื‘ื•ื“ื” ืื™ืชื. ## ืžื™ ืฆืจื™ืš ืคืชืงื™ื ืืชื’ืจ ืžืฉืžืขื•ืชื™ ื‘ืขื‘ื•ื“ื” ืขื ื’ื™ื˜ ื”ื•ื ืฉืงื•ืžื™ื˜ื™ื ืื™ื ื ื ื™ืชื ื™ื ืœืขืจื™ื›ื”. ื ื›ื•ืŸ, ืืคืฉืจ ืœืžื—ื•ืง ืงื•ืžื™ื˜ ื•ืœื™ืฆื•ืจ ืื—ืจ ื‘ืžืงื•ืžื• (ืขื ืคืงื•ื“ื•ืช ื›ืžื• ืจื™ื‘ื™ื™ืก, ืืžื ื“, ืฆ'ืจื™-ืคื™ืง), ืื‘ืœ ืžืžืฉ ืœืงื—ืช ืงื•ืžื™ื˜ ืงื™ื™ื ืฉื“ื—ืคืชื™ ืœืฉืจืช ื•ืฉืื—ืจื™ื ื”ืชื‘ืกืกื• ืขืœื™ื• ื•ื‘ื ื• ืžืžื ื• ืงื•ืžื™ื˜ื™ื ืฉืœื”ื, ื•ืœืฉื ื•ืช ืžืฉื”ื• ื‘ื”ื•ื“ืขื” ืฉืœื•, ื–ื” ื›ื‘ืจ ืœื ืคืฉื•ื˜. ื•ื›ืš ื ื•ืฆืจื• ืžื ื’ื ื•ื ื™ื ืฉืขื•ื–ืจื™ื ืœื ื• ืœื”ื•ืกื™ืฃ ื’ืžื™ืฉื•ืช ืœื’ืจืฃ ื”ืงื•ืžื™ื˜ื™ื - ืžื ื’ื ื•ื ื™ื ื›ืžื• ื‘ืจืื ืฆ'ื™ื, ืชื’ื™ื•ืช ื•ื’ื ืคืชืงื™ื. ืคืชืง ื”ื•ื ื˜ืงืกื˜ ื—ื•ืคืฉื™ ืฉืื ื™ ื™ื›ื•ืœ ืœื”ื“ื‘ื™ืง ืขืœ ืงื•ืžื™ื˜. ื”ืคืชืง ื™ื•ืคื™ืข ื‘ืœื•ื’ (ืื ืืจืฆื” ืœื”ืฆื™ื’ ืื•ืชื• ืฉื), ื”ื•ื ื ื™ืชืŸ ืœืžื—ื™ืงื”, ืขืจื™ื›ื” ื•ื”ื–ื–ื” ื•ืื ื™ ื™ื›ื•ืœ ืœื—ืคืฉ ืงื•ืžื™ื˜ื™ื ืœืคื™ ื˜ืงืกื˜ ืฉื™ืฉ ื‘ืคืชืงื™ื ืฉืœื”ื. ื•ืœืžื” ื–ื” ื˜ื•ื‘? ื”ื ื” ื›ืžื” ื“ื•ื’ืžืื•ืช: 1. ืื ื™ืฉ ืœื™ ืกืงืจื™ืคื˜ ืฉืžืจื™ืฅ Deployment ืื•ื˜ื•ืžื˜ื™ ืœืกื‘ื™ื‘ืช ื‘ื“ื™ืงื•ืช ืื—ืจื™ ืฉืขืฉื™ืชื™ ืงื•ืžื™ื˜, ืื ื™ ื™ื›ื•ืœ ืœื”ื“ื‘ื™ืง ืืช ื”ืคืœื˜ ืฉืœ ื”ืกืงืจื™ืคื˜ ื”ื–ื” ื‘ืชื•ืจ ืคืชืง ืœืงื•ืžื™ื˜ ืื—ืจื™ ืฉื”ื•ื ืขื•ืฉื” ื“ื™ืคืœื•ื™. ื‘ืฆื•ืจื” ื›ื–ืืช ืื ื™ ื™ื›ื•ืœ ืœื•ื•ื“ื ืฉื” deploy ื”ืฆืœื™ื— ื•ืœื”ื™ื–ื›ืจ ืื—ืจ ื›ืš ืื™ื–ื” ืงื•ืžื™ื˜ื™ื ื ื›ื ืกื• ื•ืžืชื™ ืœืกื‘ื™ื‘ืช ื”ื‘ื“ื™ืงื•ืช. 2. ืื•ืชื• ืกืงืจื™ืคื˜ ื™ื›ื•ืœ ืœืขืฉื•ืช deploy ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ, ื•ืื– ื”ื•ื ืฉื•ื‘ ื™ื•ืกื™ืฃ ืœื™ ื”ืขืจื” ืœืงื•ืžื™ื˜ ืฉื”ืงื•ื“ ื ื›ื ืก ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ. 3. ื”ืจื‘ื” ืคืขืžื™ื ืื ื™ ืžืฉืชืžืฉ ื‘ืœื•ื’ ืฉืœ ื’ื™ื˜ ื›ื“ื™ ืœื™ื™ืฆืจ ืจืฉื™ืžืช ืฉื™ื ื•ื™ื™ื ื›ืฉืื ื™ ืžื•ืฆื™ื ื’ื™ืจืกื”. ืืช ื”ื˜ืงืกื˜ ืฉืœ ืจืฉื™ืžืช ื”ืฉื™ื ื•ื™ื™ื ืื ื™ ืจื•ืฆื” ืœืขืจื•ืš ื’ื ืื—ืจื™ ืฉื™ืฆืจืชื™ ืืช ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜, ื•ืœื›ืŸ ืื ื™ ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืคืชืง ืขืœ ื›ืœ ืงื•ืžื™ื˜ ืžื” ื”ืฉื™ื ื•ื™ื™ื ืฉื”ื•ื ื”ื‘ื™ื, ืœืขืจื•ืš ืืช ื”ืคืชืงื™ื ื”ืืœื” ื›ืฉืฆืจื™ืš ื•ื‘ืกื•ืฃ ืœื”ื•ืฆื™ื ืจืฉื™ืžืช ืฉื™ื ื•ื™ื™ื ืžืกื•ื“ืจืช. 4. ืžืื’ืจื™ื ืžืกื•ื™ืžื™ื ื›ื•ืœืœื™ื Pipelines ืฉืžืจื™ืฆื™ื ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช ืขืœ ื›ืœ ืงื•ืžื™ื˜, ื•ืคืจื•ื™ืงื˜ื™ื ืื—ืจื™ื ืžืขืกื™ืงื™ื ืื ืฉื™ QA ืฉื™ืจื™ืฆื• ื‘ื“ื™ืงื•ืช ื‘ืฆื•ืจื” ื™ื“ื ื™ืช. ื‘ืฉื ื™ ื”ืžืงืจื™ื ื”ืชื•ืฆืื” ืฉืœ ื”ื‘ื“ื™ืงื” ืœื ื™ื›ื•ืœื” ืœื”ื•ืคื™ืข ื‘ืชื•ืจ ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜ (ื›ื™ ื”ื™ื ืœื ื”ื™ืชื” ื–ืžื™ื ื” ื›ืฉืขืฉื™ื ื• ืงื•ืžื™ื˜), ืื‘ืœ ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ื“ื‘ื™ืง ืื•ืชื” ื‘ืชื•ืจ ืคืชืง ืœืงื•ืžื™ื˜ ื”ืžืชืื™ื. ืื—ืจ ื›ืš ื ื•ื›ืœ ืœื—ืคืฉ ื‘ื™ืŸ ืชื•ืฆืื•ืช ื”ื‘ื“ื™ืงื•ืช ืื• ืœืกื ืŸ ืจืง ืงื•ืžื™ื˜ื™ื ื‘ื”ื ื›ืœ ื”ื‘ื“ื™ืงื•ืช ืขื‘ืจื•. ## ืื™ืš ืžืฉืชืžืฉื™ื ื‘ืคืชืงื™ื ืคืชืง ื”ื•ื ืžื™ื“ืข ืฉื ืฉืžืจ ื‘ืžืื’ืจ ืฉืœ ื’ื™ื˜ ื‘ืงื•ื‘ืฅ ื ืคืจื“ ืžื”ืงื•ืžื™ื˜. ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ื•ืกื™ืฃ ื›ืžื” ืคืชืงื™ื ืฉืจื•ืฆื™ื ืขืœ ื›ืœ ืงื•ืžื™ื˜ ื‘ืชื ืื™ ืฉื”ื ื™ื”ื™ื• ื‘"ื ื•ืฉืื™ื" ืฉื•ื ื™ื. ืื ื™ ื™ื•ืฆืจ ืžืื’ืจ ืจืืฉื•ืŸ ื‘ืฉื‘ื™ืœ ื”ื“ื•ื’ืžื” ืขื ื”ืคืงื•ื“ื•ืช:
$ git init .
$ git commit --allow-empty -m 'initial commit'
$ git commit --allow-empty -m 'created homepage'
$ git commit --allow-empty -m 'added about page'
$ git commit --allow-empty -m 'added admin panel'
$ git commit --allow-empty -m 'allow editing header from the admin pages'
ื”ืชื•ืฆืื” ื”ื™ื:
$ git log --oneline
0fa947b allow editing header from the admin pages
f4fa771 added admin panel
4126289 added about page
b4a7379 created homepage
ebddbeb initial commit
ืขื›ืฉื™ื• ื‘ื•ืื• ื ื•ืกื™ืฃ ื›ืžื” ืคืชืงื™ื. ื ื“ืžื™ื™ืŸ ืฉื™ืฉ ืœื ื• ืกืงืจื™ืคื˜ ืฉื™ื•ื“ืข ืœืฉืœื•ื— ืืช ื”ืคืจื•ื™ืงื˜ ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ ืื—ืจื™ ื›ืœ ืงื•ืžื™ื˜, ื•ืื•ืชื• ืกืงืจื™ืคื˜ ืจื•ืฆื” ืœื“ื•ื•ื— ืฉื”ื•ื ืขืฉื” ืืช ื”ืขื‘ื•ื“ื”. ื”ืคืงื•ื“ื” ื”ื‘ืื” ืžื•ืกื™ืคื” ืคืชืง ืžืกื•ื’ deployment ืœืงื•ืžื™ื˜ ื”ืจืืฉื•ืŸ ื‘ืžืื’ืจ:
$ git notes --ref=deploy append ebddbeb -m 'pushed to production 22/10/22 10:00'
ื•ื”ืคืงื•ื“ื” ื”ื‘ืื” ืชื•ืกื™ืฃ ืคืชืง ื“ื•ืžื” ืœืงื•ืžื™ื˜ ื”ืฉื ื™:
$ git notes --ref=deploy append b4a7379 -m 'pushed to production 25/10/22 10:00'
ืขื›ืฉื™ื• ื ื ื™ื— ืฉื™ืฉ ืœื ื• ืกืงืจื™ืคื˜ ื ื•ืกืฃ ืฉืžืจื™ืฅ ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช. ื‘ืฉื ื™ ื”ืงื•ืžื™ื˜ื™ื ื”ืจืืฉื•ื ื™ื ืœื ื”ื™ื• ืขื“ื™ื™ืŸ ื‘ื“ื™ืงื•ืช ืื‘ืœ ื‘ืงื•ืžื™ื˜ ื”ืฉืœื™ืฉื™ ื›ื‘ืจ ื›ืชื‘ืชื™ 10 ื‘ื“ื™ืงื•ืช, ื”ืกืงืจื™ืคื˜ ื”ืจื™ืฅ ืื•ืชืŸ ื•ื›ื•ืœืŸ ืขื‘ืจื•. ืื ื™ ื™ื›ื•ืœ ืœื“ืžื™ื™ืŸ ืืช ื”ืคืงื•ื“ื•ืช ื”ื‘ืื•ืช ืฉืžื•ืกื™ืคื•ืช ืคืชืงื™ื ืจืœื•ื•ื ื˜ื™ื ืžืื•ืชื• ืกืงืจื™ืคื˜ ื‘ื“ื™ืงื•ืช:
$ git notes --ref=testing append ebddbeb -m 'no tests found'
$ git notes --ref=testing append b4a7379 -m 'no tests found'
$ git notes --ref=testing append 4126289 -m 'performed 10 tests. All passed'
ืขื›ืฉื™ื• ืฉื›ืœ ื”ืคืชืงื™ื ื‘ืžืงื•ื ืื ื™ ื™ื›ื•ืœ ืœื”ืฆื™ื’ ืืช ื”ืœื•ื’ ื•ืœื”ื•ืกื™ืฃ ืœื• ืคืชืงื™ื ืžืกื•ื’ ืžืกื•ื™ื. ืœื“ื•ื’ืžื” ื–ื” ื”ืœื•ื’ ื‘ืชื•ืกืคืช ื›ืœ ื”ืคืชืงื™ื ืžืกื•ื’ testing:
0fa947b allow editing header from the admin pages
f4fa771 added admin panel
4126289 added about page
Notes (testing):
    performed 10 tests. All passed

b4a7379 created homepage
Notes (testing):
    no tests found

ebddbeb initial commit
Notes (testing):
    no tests found
ื•ื›ื“ื™ ืœื”ืฆื™ื’ ืืช ื›ืœ ื”ืคืชืงื™ื ืžื›ืœ ื”ืกื•ื’ื™ื ืื ื™ ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ื›ื•ื›ื‘ื™ืช:
$ git log --notes="*"

ToCode
1 419
# ืžื”ื Git Notes ื•ืื™ืš ื”ื ืขื•ื–ืจื™ื ืœื ื• ืœืขืฉื•ืช ืกื“ืจ ื‘ืžืื’ืจ ื’ื™ื˜ ื”ืคื™ืฆ'ืจ ืฉืœ git notes ืงื™ื™ื ื‘ื’ื™ื˜ ื›ื‘ืจ ืขืฉืจ ืฉื ื™ื ื‘ืขืจืš ืื‘ืœ ืžืขื˜ ืื ืฉื™ื ืžื›ื™ืจื™ื ืื•ืชื• ืื• ืžืฉืชืžืฉื™ื ื‘ื•. ื‘ืคื•ืกื˜ ื–ื” ื ืจืื” ืžื”ื notes ื•ืžื” ื”ืคืงื•ื“ื•ืช ื”ืžืจื›ื–ื™ื•ืช ืœืขื‘ื•ื“ื” ืื™ืชื. ## ืžื™ ืฆืจื™ืš ืคืชืงื™ื ืืชื’ืจ ืžืฉืžืขื•ืชื™ ื‘ืขื‘ื•ื“ื” ืขื ื’ื™ื˜ ื”ื•ื ืฉืงื•ืžื™ื˜ื™ื ืื™ื ื ื ื™ืชื ื™ื ืœืขืจื™ื›ื”. ื ื›ื•ืŸ, ืืคืฉืจ ืœืžื—ื•ืง ืงื•ืžื™ื˜ ื•ืœื™ืฆื•ืจ ืื—ืจ ื‘ืžืงื•ืžื• (ืขื ืคืงื•ื“ื•ืช ื›ืžื• ืจื™ื‘ื™ื™ืก, ืืžื ื“, ืฆ'ืจื™-ืคื™ืง), ืื‘ืœ ืžืžืฉ ืœืงื—ืช ืงื•ืžื™ื˜ ืงื™ื™ื ืฉื“ื—ืคืชื™ ืœืฉืจืช ื•ืฉืื—ืจื™ื ื”ืชื‘ืกืกื• ืขืœื™ื• ื•ื‘ื ื• ืžืžื ื• ืงื•ืžื™ื˜ื™ื ืฉืœื”ื, ื•ืœืฉื ื•ืช ืžืฉื”ื• ื‘ื”ื•ื“ืขื” ืฉืœื•, ื–ื” ื›ื‘ืจ ืœื ืคืฉื•ื˜. ื•ื›ืš ื ื•ืฆืจื• ืžื ื’ื ื•ื ื™ื ืฉืขื•ื–ืจื™ื ืœื ื• ืœื”ื•ืกื™ืฃ ื’ืžื™ืฉื•ืช ืœื’ืจืฃ ื”ืงื•ืžื™ื˜ื™ื - ืžื ื’ื ื•ื ื™ื ื›ืžื• ื‘ืจืื ืฆ'ื™ื, ืชื’ื™ื•ืช ื•ื’ื ืคืชืงื™ื. ืคืชืง ื”ื•ื ื˜ืงืกื˜ ื—ื•ืคืฉื™ ืฉืื ื™ ื™ื›ื•ืœ ืœื”ื“ื‘ื™ืง ืขืœ ืงื•ืžื™ื˜. ื”ืคืชืง ื™ื•ืคื™ืข ื‘ืœื•ื’ (ืื ืืจืฆื” ืœื”ืฆื™ื’ ืื•ืชื• ืฉื), ื”ื•ื ื ื™ืชืŸ ืœืžื—ื™ืงื”, ืขืจื™ื›ื” ื•ื”ื–ื–ื” ื•ืื ื™ ื™ื›ื•ืœ ืœื—ืคืฉ ืงื•ืžื™ื˜ื™ื ืœืคื™ ื˜ืงืกื˜ ืฉื™ืฉ ื‘ืคืชืงื™ื ืฉืœื”ื. ื•ืœืžื” ื–ื” ื˜ื•ื‘? ื”ื ื” ื›ืžื” ื“ื•ื’ืžืื•ืช: 1. ืื ื™ืฉ ืœื™ ืกืงืจื™ืคื˜ ืฉืžืจื™ืฅ Deployment ืื•ื˜ื•ืžื˜ื™ ืœืกื‘ื™ื‘ืช ื‘ื“ื™ืงื•ืช ืื—ืจื™ ืฉืขืฉื™ืชื™ ืงื•ืžื™ื˜, ืื ื™ ื™ื›ื•ืœ ืœื”ื“ื‘ื™ืง ืืช ื”ืคืœื˜ ืฉืœ ื”ืกืงืจื™ืคื˜ ื”ื–ื” ื‘ืชื•ืจ ืคืชืง ืœืงื•ืžื™ื˜ ืื—ืจื™ ืฉื”ื•ื ืขื•ืฉื” ื“ื™ืคืœื•ื™. ื‘ืฆื•ืจื” ื›ื–ืืช ืื ื™ ื™ื›ื•ืœ ืœื•ื•ื“ื ืฉื” deploy ื”ืฆืœื™ื— ื•ืœื”ื™ื–ื›ืจ ืื—ืจ ื›ืš ืื™ื–ื” ืงื•ืžื™ื˜ื™ื ื ื›ื ืกื• ื•ืžืชื™ ืœืกื‘ื™ื‘ืช ื”ื‘ื“ื™ืงื•ืช. 2. ืื•ืชื• ืกืงืจื™ืคื˜ ื™ื›ื•ืœ ืœืขืฉื•ืช deploy ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ, ื•ืื– ื”ื•ื ืฉื•ื‘ ื™ื•ืกื™ืฃ ืœื™ ื”ืขืจื” ืœืงื•ืžื™ื˜ ืฉื”ืงื•ื“ ื ื›ื ืก ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ. 3. ื”ืจื‘ื” ืคืขืžื™ื ืื ื™ ืžืฉืชืžืฉ ื‘ืœื•ื’ ืฉืœ ื’ื™ื˜ ื›ื“ื™ ืœื™ื™ืฆืจ ืจืฉื™ืžืช ืฉื™ื ื•ื™ื™ื ื›ืฉืื ื™ ืžื•ืฆื™ื ื’ื™ืจืกื”. ืืช ื”ื˜ืงืกื˜ ืฉืœ ืจืฉื™ืžืช ื”ืฉื™ื ื•ื™ื™ื ืื ื™ ืจื•ืฆื” ืœืขืจื•ืš ื’ื ืื—ืจื™ ืฉื™ืฆืจืชื™ ืืช ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜, ื•ืœื›ืŸ ืื ื™ ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืคืชืง ืขืœ ื›ืœ ืงื•ืžื™ื˜ ืžื” ื”ืฉื™ื ื•ื™ื™ื ืฉื”ื•ื ื”ื‘ื™ื, ืœืขืจื•ืš ืืช ื”ืคืชืงื™ื ื”ืืœื” ื›ืฉืฆืจื™ืš ื•ื‘ืกื•ืฃ ืœื”ื•ืฆื™ื ืจืฉื™ืžืช ืฉื™ื ื•ื™ื™ื ืžืกื•ื“ืจืช. 4. ืžืื’ืจื™ื ืžืกื•ื™ืžื™ื ื›ื•ืœืœื™ื Pipelines ืฉืžืจื™ืฆื™ื ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช ืขืœ ื›ืœ ืงื•ืžื™ื˜, ื•ืคืจื•ื™ืงื˜ื™ื ืื—ืจื™ื ืžืขืกื™ืงื™ื ืื ืฉื™ QA ืฉื™ืจื™ืฆื• ื‘ื“ื™ืงื•ืช ื‘ืฆื•ืจื” ื™ื“ื ื™ืช. ื‘ืฉื ื™ ื”ืžืงืจื™ื ื”ืชื•ืฆืื” ืฉืœ ื”ื‘ื“ื™ืงื” ืœื ื™ื›ื•ืœื” ืœื”ื•ืคื™ืข ื‘ืชื•ืจ ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜ (ื›ื™ ื”ื™ื ืœื ื”ื™ืชื” ื–ืžื™ื ื” ื›ืฉืขืฉื™ื ื• ืงื•ืžื™ื˜), ืื‘ืœ ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ื“ื‘ื™ืง ืื•ืชื” ื‘ืชื•ืจ ืคืชืง ืœืงื•ืžื™ื˜ ื”ืžืชืื™ื. ืื—ืจ ื›ืš ื ื•ื›ืœ ืœื—ืคืฉ ื‘ื™ืŸ ืชื•ืฆืื•ืช ื”ื‘ื“ื™ืงื•ืช ืื• ืœืกื ืŸ ืจืง ืงื•ืžื™ื˜ื™ื ื‘ื”ื ื›ืœ ื”ื‘ื“ื™ืงื•ืช ืขื‘ืจื•. ## ืื™ืš ืžืฉืชืžืฉื™ื ื‘ืคืชืงื™ื ืคืชืง ื”ื•ื ืžื™ื“ืข ืฉื ืฉืžืจ ื‘ืžืื’ืจ ืฉืœ ื’ื™ื˜ ื‘ืงื•ื‘ืฅ ื ืคืจื“ ืžื”ืงื•ืžื™ื˜. ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื”ื•ืกื™ืฃ ื›ืžื” ืคืชืงื™ื ืฉืจื•ืฆื™ื ืขืœ ื›ืœ ืงื•ืžื™ื˜ ื‘ืชื ืื™ ืฉื”ื ื™ื”ื™ื• ื‘"ื ื•ืฉืื™ื" ืฉื•ื ื™ื. ืื ื™ ื™ื•ืฆืจ ืžืื’ืจ ืจืืฉื•ืŸ ื‘ืฉื‘ื™ืœ ื”ื“ื•ื’ืžื” ืขื ื”ืคืงื•ื“ื•ืช:
$ git init .
$ git commit --allow-empty -m 'initial commit'
$ git commit --allow-empty -m 'created homepage'
$ git commit --allow-empty -m 'added about page'
$ git commit --allow-empty -m 'added admin panel'
$ git commit --allow-empty -m 'allow editing header from the admin pages'
ื”ืชื•ืฆืื” ื”ื™ื:
$ git log --oneline
0fa947b allow editing header from the admin pages
f4fa771 added admin panel
4126289 added about page
b4a7379 created homepage
ebddbeb initial commit
ืขื›ืฉื™ื• ื‘ื•ืื• ื ื•ืกื™ืฃ ื›ืžื” ืคืชืงื™ื. ื ื“ืžื™ื™ืŸ ืฉื™ืฉ ืœื ื• ืกืงืจื™ืคื˜ ืฉื™ื•ื“ืข ืœืฉืœื•ื— ืืช ื”ืคืจื•ื™ืงื˜ ืœืกื‘ื™ื‘ืช ืคืจื•ื“ืงืฉืŸ ืื—ืจื™ ื›ืœ ืงื•ืžื™ื˜, ื•ืื•ืชื• ืกืงืจื™ืคื˜ ืจื•ืฆื” ืœื“ื•ื•ื— ืฉื”ื•ื ืขืฉื” ืืช ื”ืขื‘ื•ื“ื”. ื”ืคืงื•ื“ื” ื”ื‘ืื” ืžื•ืกื™ืคื” ืคืชืง ืžืกื•ื’ deployment ืœืงื•ืžื™ื˜ ื”ืจืืฉื•ืŸ ื‘ืžืื’ืจ:
$ git notes --ref=deploy append ebddbeb -m 'pushed to production 22/10/22 10:00'
ื•ื”ืคืงื•ื“ื” ื”ื‘ืื” ืชื•ืกื™ืฃ ืคืชืง ื“ื•ืžื” ืœืงื•ืžื™ื˜ ื”ืฉื ื™:
$ git notes --ref=deploy append b4a7379 -m 'pushed to production 25/10/22 10:00'
ืขื›ืฉื™ื• ื ื ื™ื— ืฉื™ืฉ ืœื ื• ืกืงืจื™ืคื˜ ื ื•ืกืฃ ืฉืžืจื™ืฅ ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช. ื‘ืฉื ื™ ื”ืงื•ืžื™ื˜ื™ื ื”ืจืืฉื•ื ื™ื ืœื ื”ื™ื• ืขื“ื™ื™ืŸ ื‘ื“ื™ืงื•ืช ืื‘ืœ ื‘ืงื•ืžื™ื˜ ื”ืฉืœื™ืฉื™ ื›ื‘ืจ ื›ืชื‘ืชื™ 10 ื‘ื“ื™ืงื•ืช, ื”ืกืงืจื™ืคื˜ ื”ืจื™ืฅ ืื•ืชืŸ ื•ื›ื•ืœืŸ ืขื‘ืจื•. ืื ื™ ื™ื›ื•ืœ ืœื“ืžื™ื™ืŸ ืืช ื”ืคืงื•ื“ื•ืช ื”ื‘ืื•ืช ืฉืžื•ืกื™ืคื•ืช ืคืชืงื™ื ืจืœื•ื•ื ื˜ื™ื ืžืื•ืชื• ืกืงืจื™ืคื˜ ื‘ื“ื™ืงื•ืช:
$ git notes --ref=testing append ebddbeb -m 'no tests found'
$ git notes --ref=testing append b4a7379 -m 'no tests found'
$ git notes --ref=testing append 4126289 -m 'performed 10 tests. All passed'
ืขื›ืฉื™ื• ืฉื›ืœ ื”ืคืชืงื™ื ื‘ืžืงื•ื ืื ื™ ื™ื›ื•ืœ ืœื”ืฆื™ื’ ืืช ื”ืœื•ื’ ื•ืœื”ื•ืกื™ืฃ ืœื• ืคืชืงื™ื ืžืกื•ื’ ืžืกื•ื™ื. ืœื“ื•ื’ืžื” ื–ื” ื”ืœื•ื’ ื‘ืชื•ืกืคืช ื›ืœ ื”ืคืชืงื™ื ืžืกื•ื’ testing:
0fa947b allow editing header from the admin pages
f4fa771 added admin panel
4126289 added about page
Notes (testing):
    performed 10 tests. All passed

b4a7379 created homepage
Notes (testing):
    no tests found

ebddbeb initial commit
Notes (testing):
    no tests found
ื•ื›ื“ื™ ืœื”ืฆื™ื’ ืืช ื›ืœ ื”ืคืชืงื™ื ืžื›ืœ ื”ืกื•ื’ื™ื ืื ื™ ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ื›ื•ื›ื‘ื™ืช:
$ git log --notes="*"

ToCode
1 419
# ื”ื™ื•ื ืœืžื“ืชื™: ืžื” ื‘ืืžืช ื”ืคืจื™ืข ื›ืœ ื›ืš ื‘ class ื‘ React ื‘ื™ืŸ ื”ืฆืขืงื•ืช ื”ืจืืฉื•ื ื•ืช ืฉืื ื—ื ื• ืคื•ื’ืฉื™ื ื‘ืงื•ื ืกื•ืœ ื›ืฉื›ื•ืชื‘ื™ื ืจื™ืืงื˜ ื ืžืฆืืช ื”ืฆืขืงื”:
Warning: Invalid DOM property `class`. Did you mean `className`?
ืื‘ืœ ื›ื‘ืจ ื›ืžื” ืฉื ื™ื ืœืžืจื•ืช ื”ืื–ื”ืจื” ื”ืงื•ื“ ืขื“ื™ื™ืŸ ืขื•ื‘ื“. ื›ืœื•ืžืจ ื‘ืงื•ืžืคื•ื ื ื˜ื” ื”ื–ื•:
import "./styles.css";

export default function App() {
  return (
    <div class="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
ืœ div ื”ืžืจื›ื–ื™ ื™ื”ื™ื” ืืช ื”ืงืœืืก App. ืื– ืžื” ื‘ื›ืœ ื–ืืช ื”ื‘ืขื™ื”? ืžืกืชื‘ืจ ืฉื”ืกื™ืคื•ืจ ื”ื•ื ื‘ื›ืœืœ ืœื ืžื’ื‘ืœื” ื˜ื›ื ื™ืช ืฉืœ ืจื™ืืงื˜ ืืœื ื ื™ืกื™ื•ืŸ ืœื”ื’ืŸ ืขืœื™ื ื• ื”ืžืชื›ื ืชื™ื. ื‘ืฉื‘ื™ืœ ืœื›ืชื•ื‘ ืงื•ืžืคื•ื ื ื˜ื” ืฉืžืงื‘ืœืช ื‘ืชื•ืจ prop ืžืืคื™ื™ืŸ class ื™ื›ื•ืœ ืœื”ื™ื•ืช ืฉื”ื™ื™ื ื• ืžื ืกื™ื ืœื›ืชื•ื‘ ืงื•ื“ ื›ื–ื”:
export default function App(props) {
    const { class } = props;
}
ืฉืœื ื”ื™ื” ืขื•ื‘ื“ ื‘ื’ืœืœ ืฉ class ื–ื• ืžื™ืœื” ืฉืžื•ืจื”. ื•ื›ืŸ ื‘ืจื•ืจ ืฉื”ื™ื™ื ื• ื™ื›ื•ืœื™ื ืœื›ืชื•ื‘ ื‘ืžืงื•ื ืžืฉื”ื• ื›ื–ื”:
export default function App(props) {
    const { class: className } = props;
    // now I use className inside the component, to handle the "class" from outside
}
ืื‘ืœ ืืฃ ืื—ื“ ืœื ืจื•ืฆื” ืœืฉื ื•ืช ืขื›ืฉื™ื• ืืช ื›ืœ ื”ืงื•ื“ ืฉืœ ืงื•ืžืคื•ื ื ื˜ื•ืช ืงื™ื™ืžื•ืช. ื•ืœืžื” ืœื ืœืชืžื•ืš ื‘ืฉื ื™ ื”ื›ืชื™ื‘ื™ื (ืžื” ืฉื›ื‘ืจ ืงื•ืจื” ืขื›ืฉื™ื•) ื‘ืœื™ ืื–ื”ืจื”? ื”ืชืฉื•ื‘ื” ืฉืื ืœื ื”ื™ืชื” ืื–ื”ืจื” ืื– ื›ืœ ืกืคืจื™ื™ืช ืงื•ืžืคื•ื ื ื˜ื•ืช ื”ื™ืชื” ืฆืจื™ื›ื” ืœืชืžื•ืš ื‘ืฉื ื™ ื”ื›ืชื™ื‘ื™ื ื•ื–ื” ืฉื•ื‘ ื™ื›ืจื™ื— ื›ื•ืชื‘ื™ ืกืคืจื™ื•ืช ืœืฉื›ืชื‘ ื”ืจื‘ื” ืงื•ื“.

ToCode
1 419
/dailypost

ToCode
1 419
# ืžืชื™ ืœื”ืžืฉื™ืš ื”ืœืื”? ืื ื—ื ื• ื™ื•ื“ืขื™ื ืฉื™ืฉ ืžื™ื ื™ืžื•ื ื–ืžืŸ ืขื‘ื•ื“ื” ืขื ื˜ื›ื ื•ืœื•ื’ื™ื” ื›ื“ื™ ืฉื ื”ื™ื” ื™ืขื™ืœื™ื ื‘ื” - ืžื” ืฉื ืงืจื Ramp Up Time. ืื ื‘ื™ืœื™ืช ืกื•ืคืฉื‘ื•ืข ืขื ื’ื• ื›ื ืจืื” ืฉื–ื” ืœื ืžืกืคื™ืง, ื•ืขื‘ื•ืจ ืจื•ื‘ ื”ืื ืฉื™ื ืคื—ื•ืช ืžืฉื ื” ืฉืœ ื ื™ืกื™ื•ืŸ ื‘ Rails ืœื ื™ืกืคื™ืง ื‘ืฉื‘ื™ืœ ืœื”ืฉืชืชืฃ ื‘ืคืจื•ื™ืงื˜ ื’ื“ื•ืœ. ืื‘ืœ ื”ืื ื™ืฉ ื’ื ืžืงืกื™ืžื•ื ื–ืžืŸ ืขื‘ื•ื“ื” ืขื ื˜ื›ื ื•ืœื•ื’ื™ื”, ืฉืื—ืจื™ื• ื”ืžืฉืš ืขื‘ื•ื“ื” ืื™ืชื” ื”ื•ื ื‘ื–ื‘ื•ื– ื–ืžืŸ? ื”ืื ืืคืฉืจ ืœื”ื™ื•ืช ืžืกืคื™ืง ืžื ื•ืกื” ื‘ Rails? ื”ืื ื™ืฉ ื ืงื•ื“ื” ืฉื‘ื” ืื™ืŸ ืฉื•ื ืคืจื•ื™ืงื˜ ืฉื™ืœืžื“ ืื•ืชืš ืžืฉื”ื• ื—ื“ืฉ ืขืœ ื”ื˜ื›ื ื•ืœื•ื’ื™ื”? ืœื“ืขืชื™ ื”ืชืฉื•ื‘ื” ืฉืœื™ืœื™ืช. ืขื“ ืขื›ืฉื™ื• ื•ื‘ื›ืœ ื˜ื›ื ื•ืœื•ื’ื™ื” ืฉืขื‘ื“ืชื™ ืื™ืชื”, ื›ืœ ืคืขื ืฉืœืžื“ืชื™ ืžืฉื”ื• ื—ื“ืฉ ื•ื›ืœ ื ื™ืกื™ื•ืŸ ื ื•ืกืฃ ืฉื”ื™ื” ืœื™ ืขื ื”ื˜ื›ื ื•ืœื•ื’ื™ื” ืจืง ืคืชื— ืœื™ ื“ืœืชื•ืช ืœื ื•ืฉืื™ื ื—ื“ืฉื™ื ื ื•ืกืคื™ื ืฉืฆืจื™ืš ืœืœืžื•ื“. ืื ื ื™ืฉืืจ ืขื ื”ื“ื•ื’ืžื” ืฉืœ ืจื™ื™ืœืก ื›ืœ ืืœื” ืคืจื•ื™ืงื˜ื™ื ืฉืืคืฉืจ ืœืขืฉื•ืช ื•ืœืœืžื•ื“ ืžื”ื ื“ื‘ืจื™ื ื—ื“ืฉื™ื- 1. ืœื›ืชื•ื‘ ืืชืจ ื‘ืกื™ืกื™ ืขื ืžืขืจื›ืช ื ื™ื”ื•ืœ 2. ืœื›ืชื•ื‘ ืจืฉืช ื—ื‘ืจืชื™ืช 3. ืœื›ืชื•ื‘ ืืชืจ ื›ืžื• ื•ื™ืงืก - ืฉื›ืœ ืื—ื“ ื™ื›ื•ืœ ืœื™ืฆื•ืจ ืชื•ื›ืŸ ืœืขืฆืžื• 4. ืœื›ืชื•ื‘ ืžืขืจื›ืช ืฉืœ ื—ื ื•ืช ื“ื™ื’ื™ื˜ืœื™ืช 5. ืœื›ืชื•ื‘ API ื•ืœืชืงืฉืจ ืื™ืชื• ืžืชื•ืš ืืคืœื™ืงืฆื™ื™ืช Front End 6. ืœื›ืชื•ื‘ Rails Engine ื”ืžืฉื•ืชืฃ ืœืžืกืคืจ ืคืจื•ื™ืงื˜ื™ื 7. ืœื›ืชื•ื‘ ื•ืœื”ืคื™ืฅ Rails Gem 8. ืœืฉื›ืชื‘ ืืช ื” Rails Gem ืฉืœืš ื›ืฉื™ืฉ ืœืš ื”ืจื‘ื” ืžืฉืชืžืฉื™ื ื•ืืชื” ืžื’ืœื” ืฉื” API ื›ื‘ืจ ืœื ืžืกืคื™ืง ื˜ื•ื‘ 9. ืœื›ืชื•ื‘ ืžืขืจื›ืช Real Time Web ื‘ื” ื’ื•ืœืฉื™ื ืžืฉืชืคื™ื ืชื•ื›ืŸ ื•ืจื•ืื™ื ืชื•ื›ืŸ ืฉืœ ืื—ืจื™ื ื‘ื–ืžืŸ ืืžืช 10. ืœืชืงืŸ ื‘ืขื™ื•ืช ืื‘ื˜ื—ื” ื‘ืฉืจืช ืจื™ื™ืœืก ืฉื ืคืจืฅ 11. ืœื”ืงื™ื ืžืขืจื›ืช ื‘ื“ื™ืงื•ืช ืœืืคืœื™ืงืฆื™ื™ืช ืจื™ื™ืœืก ื’ื“ื•ืœื”, ืขื ื—ืœื•ืงื” ื˜ื•ื‘ื” ืœืกื•ื’ื™ ื”ื‘ื“ื™ืงื•ืช 12. ืœืชืงืŸ ื‘ืขื™ื•ืช ื‘ื™ืฆื•ืขื™ื ื• Deadlocks ื‘ืžืขืจื›ืช ื’ื“ื•ืœื” ืขืงื‘ ืขื•ืžืก ืžืฉืชืžืฉื™ื ื•ื”ืจืฉื™ืžื” ื›ืžื•ื‘ืŸ ื™ื›ื•ืœื” ืœื”ืชืืจืš ืขื•ื“ ื•ืขื•ื“, ื•ื›ื›ืœ ืฉื ื”ื™ื” ื™ื•ืชืจ ืกืคืฆื™ืคื™ื™ื ื”ื™ื ืชื”ื™ื” ื™ื•ืชืจ ืืจื•ื›ื”. ื‘ืขื•ืœื ื”ื˜ื›ื ื•ืœื•ื’ื™ ืฉืœ ื”ื™ื•ื ืžื™ื•ืžื ื•ืช ืฉื•ื•ื” ื”ืจื‘ื”, ื•ื›ื›ืœ ืฉื”ืžื™ื•ืžื ื•ืช ื’ื‘ื•ื”ื” ื™ื•ืชืจ ื”ื™ื ืฉื•ื•ื” ื™ื•ืชืจ. ืืชื ืœื ื‘ืงืฆื”, ืืชื ืืคื™ืœื• ืœื ืงืจื•ื‘ื™ื ืœืฉื. ื”ืžืฉืš ืœื™ืžื•ื“, ื”ืžืฉืš ืคื•ืงื•ืก ื•ื—ื™ืคื•ืฉ ืคืจื•ื™ืงื˜ื™ื ื—ื“ืฉื™ื ื‘ืจืžื” ื™ื•ืชืจ ื’ื‘ื•ื”ื” ืื‘ืœ ื‘ืื•ืชื” ื˜ื›ื ื•ืœื•ื’ื™ื” ื”ื•ื ื‘ื“ืจืš ื›ืœืœ ื”ื“ืจืš ื”ื˜ื•ื‘ื” ื‘ื™ื•ืชืจ ืœื”ืชืงื“ื ื›ืžืชื›ื ืชื™ื. (ื .ื‘. ื›ืŸ ื™ืฉ ื˜ื›ื ื•ืœื•ื’ื™ื•ืช ืžืชื•ืช. ื–ื” ืœื ืขื•ื–ืจ ืœื”ื™ื•ืช ืžื•ืžื—ื” ืกื™ืžื‘ื™ืืŸ ื”ื™ื•ื. ื•ื›ืŸ ื’ื ื”ื˜ื›ื ื•ืœื•ื’ื™ื•ืช ืฉืื ื—ื ื• ืขื›ืฉื™ื• ืขื•ื‘ื“ื™ื ืขืœื™ื”ืŸ ื™ืžื•ืชื•. ืื‘ืœ ืื ืขื‘ื“ืช 6 ืฉื ื™ื ื‘ืจื™ืืงื˜ ื•ืืช ืžืชืœื‘ื˜ืช ืื ืœื”ืžืฉื™ืš ื‘ืจื™ืืงื˜ ืื• ืœืขื‘ื•ืจ ืœืื ื’ื•ืœืจ, ืžืฉืชืœื ืœื—ืคืฉ ืคืจื•ื™ืงื˜ ืจื™ืืงื˜ ื˜ื•ื‘ ื™ื•ืชืจ).

ToCode
1 419
/dailypost

ToCode
1 419
# ืฉืžื•ื ื” ืขืฉืจื” ืชืจื’ื™ืœื™ ื’ื™ื˜ ื›ื“ื™ ืœื”ื‘ื™ืŸ ืื™ืš ืขื•ื‘ื“ื™ื ืขื Remotes ืœื ืžื–ืžืŸ ืคืจืกืžืชื™ ืคื” ืกื™ื“ืจื” ืฉืœ ืฉืžื•ื ื” ืขืฉืจื” ืชืจื’ื™ืœื™ ื’ื™ื˜ ืฉืžืชืจื’ืœื™ื ืขื‘ื•ื“ื” ืขื ืงื•ืžื™ื˜ื™ื ื•ืขื ืคื™ื ืขืœ ืžื›ื•ื ื” ืžืงื•ืžื™ืช ื•ื›ื‘ืจ ื—ื•ื“ืฉ ืฉืื ื™ ืžื—ืคืฉ ื”ื–ื“ืžื ื•ืช ืœื›ืชื•ื‘ ืืช ื”ื—ืœืง ื”ืฉื ื™ ืฉืœ ื”ืจืฉื™ืžื” - ืชืจื’ื™ืœื™ ื’ื™ื˜ ืฉื™ืขื–ืจื• ืœื ื• ืœื”ืชืืžืŸ ืขืœ ืขื‘ื•ื“ื” ืขื Git Remote Repositories. ## 18 ืชืจื’ื™ืœื™ ื’ื™ื˜ ืขืœ ืขื‘ื•ื“ื” ืขื ืžืื’ืจื™ื ืžืจื•ื—ืงื™ื 1. ืฆืจื• ืžืื’ืจ ืจื™ืง (Bare Repository) ื‘ืชื™ืงื™ื” ื—ื“ืฉื” ืขืœ ื”ืžื—ืฉื‘ ืฉืœื›ื 2. ืฆืจื• Clone ืฉืœ ื”ืžืื’ืจ ื‘ืชื™ืงื™ื” ื‘ืฉื clone1 3. ืฆืจื• ืงื•ื‘ืฅ ื—ื“ืฉ ื‘ clone1, ื‘ืฆืขื• ืงื•ืžื™ื˜, ื•ืื– ืฉื ื• ืื•ืชื• ื›ืžื” ืคืขืžื™ื ื•ื”ืžืฉื™ื›ื• ืœืขืฉื•ืช ืงื•ืžื™ื˜ื™ื. ื‘ืกื•ืฃ ื”ืคืขื™ืœื• push ื›ื“ื™ ืœื“ื—ื•ืฃ ืืช ื›ืœ ื”ืงื•ืžื™ื˜ื™ื ืœืžืื’ืจ. ื‘ืฆืขื• ืืช ืื•ืชื• ื“ื‘ืจ ื‘ branch ื—ื“ืฉ ื•ื“ื—ืคื• ื’ื ืื•ืชื•. 4. ื•ื•ื“ืื• ืฉืืชื ืžืฆืœื™ื—ื™ื ืœืจืื•ืช ืืช ื›ืœ ื”ืงื•ืžื™ื˜ื™ื ื•ื”ืขื ืฃ ื”ื—ื“ืฉ ื‘ืžืื’ืจ ื”ืจื™ืง ื”ืžืงื•ืจื™. 5. ืฆืจื• Clone ื—ื“ืฉ ืฉืœ ื”ืžืื’ืจ ื‘ืชื™ืงื™ื” ื‘ืฉื clone2. ืขื›ืฉื™ื• ื™ืฉ ืœื ื• ืฉื ื™ ืžืฉืชืžืฉื™ื ืฉืขื•ื‘ื“ื™ื ืขืœ ืžืื’ืจ ืžืฉื•ืชืฃ. ื•ื›ืœ ื–ื” ื‘ืœื™ ื’ื™ื˜ื”ืื‘. 6. ืฆืจื• ืงื•ืžื™ื˜ ื‘ clone1, ื“ื—ืคื• ืื•ืชื• ืœืžืื’ืจ ื”ืžืฉื•ืชืฃ ื•ื”ืคืขื™ืœื• pull ืž clone2. 7. ืฆืจื• ืงื•ืžื™ื˜ ื‘ clone1, ื“ื—ืคื• ืื•ืชื• ื•ืื– ื‘ clone2 ื”ืคืขื™ืœื• fetch ื•ืื– merge ื™ื“ื ื™ืช. 8. ืฆืจื• ืงื•ืžื™ื˜ ื—ื“ืฉ ื‘ clone1 ื•ืงื•ืžื™ื˜ ืื—ืจ ื‘ clone2. ื”ืคืขื™ืœื• push ืž clone1 ื• fetch ืž clone2, ื•ืื– ื”ืฉืชืžืฉื• ื‘ merge ื›ื“ื™ ืœืžื–ื’ ืืช ื”ืฉื™ื ื•ื™ื™ื ืœ clone2. ื“ื—ืคื• ืœืžืื’ืจ ืืช ื”ืชื•ืฆืื” ื•ืžืฉื›ื• ืื•ืชื” ืž clone1. 9. ืฆืจื• ืงื•ืžื™ื˜ ื—ื“ืฉ ื‘ clone1 ื•ืงื•ืžื™ื˜ ืื—ืจ ื‘ clone2. ื”ืคืขื™ืœื• push ืž clone1 ื• fetch ืž clone2, ื•ืื– ื”ืฉืชืžืฉื• ื‘ rebase ื›ื“ื™ ืœืžื–ื’ ืืช ื”ืฉื™ื ื•ื™ื™ื ื‘ clone2. ืื—ืจื™ ืฉื”ื›ืœ ื‘ืžืงื•ื ื”ืคืขื™ืœื• push ื• pull ื›ื“ื™ ืœืกื ื›ืจืŸ ืืช ืฉื ื™ ื”ืขื•ืชืงื™ื. 10. ื—ื–ืจื• ืขืœ ืกืขื™ืคื™ื 8 ื•-9, ื”ืคืขื ื”ืฉืชืžืฉื• ื‘ git pull ื•ื‘ git pull --rebase ื‘ื”ืชืืžื” ื‘ืžืงื•ื ื‘ fetch. 11. ืฆืจื• ืขื ืฃ ื—ื“ืฉ ื‘ clone1, ืฆืจื• ืงื•ืžื™ื˜ ื‘ืขื ืฃ ื–ื” ื•ื“ื—ืคื• ืœืžืื’ืจ. ื”ืคืขื™ืœื• fetch ืž clone2. ื”ืื ืืชื ื™ื›ื•ืœื™ื ืœืจืื•ืช ืืช ื”ืขื ืฃ ื”ื—ื“ืฉ? 12. ื‘ clone1 ืชืงื ื• ืืช ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜ ืฉืœ ื”ืงื•ืžื™ื˜ ื”ืื—ืจื•ืŸ ืขื git commit --amend. ื”ืคืขื™ืœื• pull ื‘ clone2. ื”ืื ืืชื ื™ื›ื•ืœื™ื ืœืจืื•ืช ืืช ื”ืฉื™ื ื•ื™? ื”ืื ืžืฉื”ื• ื ืฉื‘ืจ? 13. ืขื›ืฉื™ื• ื”ื’ื™ืข ื”ื–ืžืŸ ืœืฉื‘ื•ืจ ื“ื‘ืจื™ื: - ืขื‘ืจื• ืœืขื ืฃ main ื‘ืฉื ื™ ื”ืขื•ืชืงื™ื - ื‘ clone1 ืฆืจื• ืงื•ืžื™ื˜ ื•ื“ื—ืคื• - ื‘ clone2 ื”ืคืขื™ืœื• pull, ืฆืจื• ืงื•ืžื™ื˜ ื—ื“ืฉ ื•ื“ื—ืคื• - ืขื›ืฉื™ื• ื‘ clone1 ืชืงื ื• ืืช ื”ื•ื“ืขืช ื”ืงื•ืžื™ื˜ ื”ืื—ืจื•ื ื” ืขื git commit --amend. - ื‘ clone2 ื”ืคืขื™ืœื• pull - ืžื” ืงืจื”? 14. ืชืงื ื• ืืช ื”ืงื•ื ืคืœื™ืงื˜ ืฉื ื•ืฆืจ, ื‘ืฆืขื• ืงื•ืžื™ื˜ ื•ื“ื—ืคื•. ืืœ ืชืคืขื™ืœื• ืขื“ื™ื™ืŸ pull ื‘ clone1. ื‘ืฉื ื™ ื”ืžืื’ืจื™ื ื”ืคืขื™ืœื• git log --oneline --graph. ืžื” ื”ื‘ืขื™ื” ืฉืืชื ืžื–ื”ื™ื ื‘ื”ื™ืกื˜ื•ืจื™ื”? 15. ื”ืคืขื™ืœื• git pull ื‘ clone1. ื”ืคืขื™ืœื• git log --oneline --graph ืฉื•ื‘. ื•ื•ื“ืื• ืฉืฉื ื™ ื”ืžืื’ืจื™ื ืžืกื•ื ื›ืจื ื™ื ื•ืฉืื•ืชื” ื‘ืขื™ื” ื‘ื”ื™ืกื˜ื•ืจื™ื” ืžื•ืคื™ืขื” ืขื›ืฉื™ื• ื‘ืฉื ื™ื”ื. 16. ื—ื–ืจื• ืขืœ ืชืจื’ื™ืœื™ื 13, 14 ื• 15 ืืš ื”ืคืขื ื”ืฉืชืžืฉื• ื‘ git pull --rebase ื‘ืžืงื•ื ื‘ pull. ืžื” ืงืจื” ื”ืคืขื? 17. ื”ืฉืชืžืฉื• ื‘ git reflog ื‘ืชื™ืงื™ื™ืช clone2 ื›ื“ื™ ืœืžืฆื•ื ืืช ื”ืงื•ืžื™ื˜ ืฉื ืขืœื ืœื›ื ื‘ืจื™ื‘ื™ื™ืก.A 18. ื”ืฉืชืžืฉื• ื‘ git cherry-pick ื›ื“ื™ ืœืฉื—ื–ืจ ืืช ื”ืงื•ืžื™ื˜ ื”ื ืขืœื. ## ื”ืขืจื” ืขืœ ืคื™ืชืจื•ื ื•ืช ื‘ืคืขื ื”ืงื•ื“ืžืช ืฉืคืจืกืžืชื™ ืจืฉื™ืžื” ื›ื–ืืช ื”ืจื‘ื” ืื ืฉื™ื ืฉืืœื• ืขืœ ืคื™ืชืจื•ื ื•ืช. ืื ื™ ืœื ื—ื•ืฉื‘ ืฉืคื™ืจืกื•ื ืคื™ืชืจื•ื ื•ืช ื™ื•ืกื™ืฃ ืœืคื•ืกื˜ ื›ื–ื” ืื• ื™ื•ืขื™ืœ ืœืžื™ ืฉืงื•ืจื ืื•ืชื•. ื”ื“ืจืš ืœื”ืชื™ื—ืก ืœืคื•ืกื˜ ื›ื–ื” ื”ื™ื ืœืงื—ืช ืžืคื” ืจืขื™ื•ื ื•ืช ืœื“ื‘ืจื™ื ืฉืฉื•ื•ื” ืœื ืกื•ืช ืœื‘ื“. ืื ืืชื ืœื ื™ื•ื“ืขื™ื ืื™ืš ืœื”ืฉืชืžืฉ ื‘ืื—ืช ื”ืคืงื•ื“ื•ืช ื›ื“ื™ ืœื ืกื•ืช ืœื‘ื“ ืืช ื”ืชืจื’ื™ืœ ืื– ืฉื•ื•ื” ืœืงืจื•ื ืขืœื™ื”. ืืคืฉืจ ื•ืจืฆื•ื™ ืœื—ืคืฉ ื‘ื’ื•ื’ืœ. ื”ืžื˜ืจื” ื”ื™ื ืœื "ืœื“ืขืช" ืืช ื›ืœ ื”ืชืฉื•ื‘ื•ืช, ืืœื ืœื‘ืœื•ืช ื™ื•ืชืจ ื–ืžืŸ ืขื ืจืฉื™ืžืช ื”ืชืจื’ื™ืœื™ื ื”ื–ืืช, ืœื‘ืœื•ืช ื™ื•ืชืจ ื–ืžืŸ ื‘ืžืฉื—ืง ืขื ื’ื™ื˜ ื•ื™ื•ืชืจ ื–ืžืŸ ื‘ื—ื™ืคื•ืฉ ื•ืงืจื™ืื” ืขืœ ื’ื™ื˜ ื‘ืจืฉืช.

ToCode
1 419
ืื‘ืœ ื–ื” ืœื ื”ื›ืœ - ื‘ืขื‘ื•ื“ื” ืขื ืจื™ืืงื˜ ื™ืฉ ืคืœืื’ื™ืŸ ืฉื ืงืจื react refresh ืฉื—ื™ื™ื‘ื™ื ืœื˜ืขื•ืŸ ืžืชื•ืš ื” HTML. ื•ื™ื˜ ื”ื™ื” ืžืขื“ื›ืŸ ืืช ื” HTML ืื ื”ื™ื” ื™ื›ื•ืœ, ืื‘ืœ ืื ื—ื ื• ืžื’ื™ืฉื™ื ืืช ื” HTML ื“ืจืš ืจื™ื™ืœืก ื•ืœื›ืŸ ืฆืจื™ืš ืœื”ื•ืกื™ืฃ ืืช ื”ืขื“ื›ื•ืŸ ื™ื“ื ื™ืช ืœืงื•ื‘ืฅ ื” layout. ืื—ืจื™ ื”ืขื“ื›ื•ืŸ ื”ืงื•ื‘ืฅ app/views/layouts/application.html.erb ื ืจืื” ื›ืš:
<!DOCTYPE html>
<html>
  <head>
    <title>HelloReactWorld1</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>


    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>

<script type="module">
import RefreshRuntime from "/vite-dev/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>

    <%= vite_client_tag %>
  </head>

  <body>
    <div id="app"></div>
    <%= vite_javascript_tag 'application.jsx' %>
  </body>
</html>
## ืคื™ืชื•ื— ืงื•ื“ ืฆื“ ืœืงื•ื— ื ืžืฉื™ืš ืœื›ืชื™ื‘ืช ืงื•ื“ ืจื™ืืงื˜ ืฉื™ื•ืจื›ื‘ ืžื“ืฃ ื‘ื™ืช, ื“ืฃ ืื•ื“ื•ืช ื•ืงื•ื‘ืฅ ื ื™ืชื•ื‘. ื‘ืฉื‘ื™ืœ ื“ืฃ ื”ื‘ื™ืช ืื ื™ ื™ื•ืฆืจ ืชื™ืงื™ื” ื—ื“ืฉื”:
$ mkdir app/javascript/routes
ื•ื‘ืชื•ื›ื” ื™ื•ืฆืจ ืืช ื”ืงื•ื‘ืฅ app/javascript/routes/homepage.jsx ืขื ื”ืชื•ื›ืŸ ื”ื‘ื:
import React, { useState } from 'react';
import { Link } from "react-router-dom";

export default function Homepage() {
  const [name, setName] = useState('');

  return (
    <div>
      <label>
        Please type your name:
        <input type="text" value={name} onChange={(e) => setName(e.currentTarget.value)} />
      </label>
      {name !== '' && <p>Hello! {name}</p>}
      <Link to="/about/index">About Us</Link> 

    </div>
  );
}
ื•ื‘ืงื•ื‘ืฅ app/javaascript/entrypoints/application.jsx ืื ื™ ืžื•ื—ืง ืืช ื›ืœ ื”ืชื•ื›ืŸ ื•ื‘ืžืงื•ืžื• ื›ื•ืชื‘ ืืช ื”ืชื•ื›ืŸ ื”ื‘ื:
import React from "react";
import { createRoot } from 'react-dom/client';
import Homepage from "../routes/homepage";
import About from '../routes/about';
import {
  BrowserRouter as Router,
  Route,
  Routes,
} from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Homepage />} />
        <Route path="/about/index" element={<About />} />
      </Routes>
    </Router>
  );
}

const root = createRoot(document.querySelector('#app'));
root.render(<App />);
ื”ืงื•ื‘ืฅ ื”ืฉืœื™ืฉื™ ืฉืœ ื”ื™ื™ืฉื•ื ื ืงืจื app/javascript/routes/about.jsx ื•ื‘ื• ืื ื™ ื›ื•ืชื‘ ืืช ื”ืชื•ื›ืŸ ื”ื‘ื:
import React from 'react';

import { Link } from "react-router-dom";

export default function About() {
  return (
    <div>
      <p>About Us</p>
      <Link to="/">Back Home</Link> 
    </div>
  );
}
## ื”ืจืฆื” ื•ื‘ื“ื™ืงื” ืื ื—ื ื• ืžื•ื›ื ื™ื ืœืฆืืช ืœื“ืจืš. ื ืคืขื™ืœ ื‘ื—ืœื•ืŸ ื ืคืจื“ ืืช ื”ืคืงื•ื“ื”:
$ ./bin/vite dev
ื•ื‘ื—ืœื•ืŸ ื ื•ืกืฃ ืืช ื”ืคืงื•ื“ื”:
$ ./bin/rails s
ื•ืขื›ืฉื™ื• ืืคืฉืจ ืœื”ื™ื›ื ืก ืžื“ืคื“ืคืŸ ืœ localhost:3000 ื•ืœืจืื•ืช ืืช ื“ืฃ ื”ืจื™ืืงื˜ ื”ืจืืฉื•ืŸ ืฉื™ืฆืจื ื•, ืœืœื—ื•ืฅ ืขืœ ื”ืงื™ืฉื•ืจ ื•ืœื”ื’ื™ืข ืœื“ืฃ ื”ืฉื ื™.

ToCode
1 419
# ืžื“ืจื™ืš: ื™ืฆื™ืจืช ืืคืœื™ืงืฆื™ื™ืช React ื‘ืชื•ืš ืฉืจืช Rails 7 ื–ื” ืžืจื’ื™ืฉ ื›ืื™ืœื• ืจืง ืืชืžื•ืœ ืคืจืกืžืชื™ ื›ืืŸ ืžื“ืจื™ืš ืื™ืš ืœืขื‘ื•ื“ ืขื React ื‘ Rails 6 ื•ื”ื ื” ื™ืฆืื” ืจื™ื™ืœืก 7 ืขื ื’ื™ืฉื” ื—ื“ืฉื” ืœื’ืžืจื™ ืœืขื‘ื•ื“ื” ืขื JavaScript. ื‘ืคื•ืกื˜ ื–ื” ื ืจืื” ืืช ื”ื’'ื vite-ruby ืฉืžืืคืฉืจ ืœื ื• ืœื‘ื ื•ืช ืืคืœื™ืงืฆื™ื™ืช ืจื™ืืงื˜ ืขื ืจื™ื™ืœืก 7 ื’ื ื‘ืœื™ webpacker. ื”ืฉื™ื ื•ื™ ื”ื’ื“ื•ืœ ื”ืžืจื›ื–ื™ ืฉืœ Rails 7 ื‘ื™ื—ืก ืœืขื‘ื•ื“ื” ืขื JavaScript ื”ื•ื ื”ื”ื—ืœื˜ื” ืœื•ื•ืชืจ ืขืœ ืฉืœื‘ ื” Precompilation. ื”ื˜ืขื ื” ืฉืœ DHH ื”ื™ื ืฉื”ื˜ื›ื ื•ืœื•ื’ื™ื•ืช ื‘ืฉืœื•ืช: ืขื HTTP Push ืืคืฉืจ ืœื”ื—ืœื™ืฃ ืืช ื” Bundling ื‘ืœื™ ืœืื‘ื“ ื‘ื™ืฆื•ืขื™ื, ื•ื“ืคื“ืคื ื™ื ื™ื•ื“ืขื™ื ื›ื‘ืจ ืœื”ืจื™ืฅ JavaScript ื‘ืจืžื” ื˜ื•ื‘ื” ื›ืš ืฉืœื ืฆืจื™ืš Babel. ื ื›ื•ืŸ, ืื ื—ื ื• ืžืคืกื™ื“ื™ื ืืช scss ืื‘ืœ ืื•ืœื™ ื–ื” ืœื ืกื•ืฃ ื”ืขื•ืœื. ื”ืงื•ืจื‘ืŸ ื”ื’ื“ื•ืœ ื‘ื™ื•ืชืจ ืฉืœ ื”ื”ื—ืœื˜ื” ื”ื–ืืช ื”ื•ื ื“ื•ื•ืงื JSX, ื›ื™ ื‘ืœื™ pre-compilation ืื™ืŸ ืžื™ ืฉื™ื”ืคื•ืš ืืช ื” JSX-ื™ื ืœืงื•ื“ JavaScript ืจื’ื™ืœ. ืœืคื ื™ ื›ืžื” ื™ืžื™ื ื›ืชื‘ืชื™ ืขืœ ืกืคืจื™ื™ืช htm ื•ื”ื™ื ื™ื•ื ืื—ื“ ืชื”ื™ื” ื”ืžืคืชื— ืœื—ื™ื‘ื•ืจ. ื”ื‘ืขื™ื” ืฉื›ืจื’ืข ื”ืขื‘ื•ื“ื” ืขื jspm ื•ื‘ืื•ืคืŸ ื›ืœืœื™ ืขื import maps ืœื ืžืกืคื™ืง ื™ืฆื™ื‘ื” - ื”ืจื‘ื” ืžื•ื“ื•ืœื™ื ื‘ jspm ื™ื™ื›ืฉืœื• ืื ื ื ืกื” ืœื”ื•ืจื™ื“ ืื•ืชื ืืœื™ื ื•, ื•ืื—ืจื™ื ื™ื™ื›ืฉืœื• ื‘ื›ืœ ืžืงืจื”. ื›ืŸ ืืคืฉืจ ืœืชืงืŸ ื›ืœ ืชืงืœื”, ืื‘ืœ ืื ืืชื ืจื•ืฆื™ื ืฉื”ื›ืœื™ื ื™ืขื‘ื“ื• ื‘ืฉื‘ื™ืœื›ื ื•ืœื ืืชื ื‘ืฉื‘ื™ืœ ื”ื›ืœื™ื ืื ื™ ืžืžืœื™ืฅ ื‘ื™ื ืชื™ื™ื ืœื—ื›ื•ืช ืขื import maps. ืžืฆื“ ืฉื ื™ ื”ื’'ื webpacker ื ืžืฆื ืžืžืฉ ื‘ืกื•ืฃ ื“ืจื›ื• ื”ืžืงืฆื•ืขื™ืช ื•ืœื›ืŸ ื ืฆื˜ืจืš ื“ืจืš ืื—ืจืช ืœืฉืœื‘ ื‘ื™ืŸ ืงื•ื“ ืจื™ื™ืœืก ืœืงื•ื“ ืคืจื•ื ื˜ ืื ื“. ื”ื“ืจืš ื”ื–ืืช ื”ื™ื ื”ื’'ื vite-rails. ื”ืชื•ื›ื ื™ืช ืฉืœื ื• ืœืคื•ืกื˜: 1. ื ื‘ื ื” ืืคืœื™ืงืฆื™ื™ืช ืจื™ื™ืœืก ื•ืืคืœื™ืงืฆื™ื™ืช ืจื™ืืงื˜ ืฉืžื—ื•ื‘ืจืช ืืœื™ื” ื‘ืืžืฆืขื•ืช ื”ื’'ื vite-rails. 2. ื ืขื‘ื™ืจ ืžืฉืชื ื™ื ืžืจื™ื™ืœืก ืœืจื™ืืงื˜ ื‘ืืžืฆืขื•ืช ื”ื’'ื gon. 3. ื ืฉืชืžืฉ ื‘ืจื™ืืงื˜ ืจืื•ื˜ืจ ื›ื“ื™ ืœื˜ืขื•ืŸ ืืช ื”ื“ืฃ ื”ืžืชืื™ื ื‘ืืคืœื™ืงืฆื™ื™ืช ื”ืจื™ืืงื˜. ืžื•ื›ื ื™ื? ื‘ื•ืื• ื ืฆื ืœื“ืจืš. ## ื”ืงืžืช ืืคืœื™ืงืฆื™ื™ืช ืจื™ื™ืœืก ื—ื“ืฉื” ืงื•ื“ื ื›ืœ ืื ื™ ืžื•ื•ื“ื ืฉืจื™ื™ืœืก 7 ืžื•ืชืงืŸ ืœื™ ืขืœ ื”ืžื—ืฉื‘ ืขื:
$ rails --version
Rails 7.0.3
ื™ื•ืฆืจ ืืคืœื™ืงืฆื™ื” ื—ื“ืฉื”:
$ rails new HelloReactWorld1
ื ื›ื ืก ืœืชื™ืงื™ื”:
$ cd HelloReactWorld1
ื‘ื’ืœืœ ืฉืื ื™ ืฆืจื™ืš ืฉื›ืœ ื” Controllers ื‘ืืคืœื™ืงืฆื™ื” ื™ื’ื™ืขื• ืœืจื™ืืงื˜, ืื ื™ ืžืขื“ื™ืฃ ืœืขื“ื›ืŸ ืืช ื” Layout ืฉื™ืชืื™ื ืœื™ ืœืจื™ืืงื˜ ื•ืœื ืœื”ืฉืชืžืฉ ื‘ืฉื›ื‘ืช ื” Views ืฉืœ ืจื™ื™ืœืก. ืื ื™ ืžืขื“ื›ืŸ ืืช ื”ืงื•ื‘ืฅ app/views/layouts/application.html.erb ื•ื›ื•ืชื‘ ื‘ื• ืืช ื”ืชื•ื›ืŸ ื”ื‘ื:
<!DOCTYPE html>
<html>
  <head>
    <title>HelloReactWorld1</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>

  <body>
    <div id="app"></div>
  </body>
</html>
ืขื›ืฉื™ื• ื”ื’ื™ืข ื”ื–ืžืŸ ืœื™ืฆื•ืจ ืฉื ื™ ืงื•ื ื˜ืจื•ืœืจื™ื ื‘ืฉื‘ื™ืœ ืฉื ื™ ื“ืคื™ื ื‘ืืชืจ. ืžืฉื•ืจืช ื”ืคืงื•ื“ื” ืื ื™ ืžืจื™ืฅ:
$ rails g controller home index
$ rails g controller about index
ื•ื ืขื“ื›ืŸ ืืช ื”ืงื•ื‘ืฅ config/routes.rb ืœืชื•ื›ืŸ ื”ื‘ื:
Rails.application.routes.draw do
  root to: 'home#index'
  get 'about/index'
end
## ื”ื•ืกืคืช ืืคืœื™ืงืฆื™ื™ืช ืฆื“ ืœืงื•ื— ืขื vite ืžืฉื•ืจืช ื”ืคืงื•ื“ื” ืžืชืงื™ื ื™ื ืืช ื”ื’'ื:
$ bundle add vite_rails
ืžื™ื™ืฆืจื™ื ืืช ื”ืกื˜ืืจื˜ืจื™ื ืขื:
$ bundle exec vite install
ื•ืขื›ืฉื™ื• ืฆืจื™ืš ืœื”ืชืงื™ืŸ ืืช ื”ืชืžื™ื›ื” ื‘ืจื™ืืงื˜. ืžืขื“ื›ื ื™ื ืืช ื”ืงื•ื‘ืฅ vite.config.ts ืฉื ื•ืฆืจ ื‘ืชื™ืงื™ื” ื”ืจืืฉื™ืช ืฉืœ ื”ืคืจื•ื™ืงื˜ ืœืชื•ื›ืŸ ื”ื‘ื:
import { defineConfig } from 'vite';
import RubyPlugin from 'vite-plugin-ruby';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [
    RubyPlugin(),
    react(),
  ],
})
ืžืคืขื™ืœื™ื ืžืฉื•ืจืช ื”ืคืงื•ื“ื” ื‘ืชื™ืงื™ื” ื”ืจืืฉื™ืช ืฉืœ ื”ืคืจื•ื™ืงื˜ ืืช ื”ืคืงื•ื“ื”:
$ npm install --save @vitejs/plugin-react react react-dom react-router-dom@6 react-refresh
ื•ืื ื—ื ื• ื›ืžืขื˜ ืžื•ื›ื ื™ื. ื ืงื•ื“ืช ื”ื›ื ื™ืกื” ืฉืœื ื• ืœืžืขืจื›ืช ื”ื™ื ื”ืงื•ื‘ืฅ app/javascript/entrypoints/application.js, ืื‘ืœ ืื ื™ ื”ื™ื™ืชื™ ืžืขื“ื™ืฃ ืฉื”ื•ื ื™ื”ื™ื” ืขื ื”ืกื™ื•ืžืช jsx ื›ื“ื™ ืฉืื•ื›ืœ ืœื›ืชื•ื‘ ื‘ื• ืงื•ื“ jsx. ืœื›ืŸ ื ืฉื ื” ืœื• ืืช ื”ืฉื ืœ application.jsx:
$ mv app/javascript/entrypoints/application.js app/javascript/entrypoints/application.jsx
ื•ื‘ืžืงื‘ื™ืœ ื‘ืงื•ื‘ืฅ app/views/layouts/application.html.erb ืื ื™ ืžื—ืœื™ืฃ ืืช ื”ืฉื•ืจื” ืฉืžืชื—ื™ืœื” ื‘ vite_javascript_tag ื•ื‘ืžืงื•ืžื” ื›ื•ืชื‘:
<%= vite_javascript_tag 'application.jsx' %>