Rails 7과 htm으로 리액션을 해보도록 하겠습니다.

17229 단어 htmReactRails7Rails
Rails7 습격
Rails 7이 나왔기 때문에 오랜만에 Type Script에서 돌아왔는데 앞부분에 큰 변화가 생긴 것 같아서 조사를 많이 해봤어요.
Rails7의 전단은 기본적으로 importmaps의 구조입니다. 이것은 좋은 구조이지만 설명할 보도가 많기 때문에 이 글에는 언급되지 않을 것입니다.
나의 주의를 끄는 것은 이 동영상이다.
Rails+importmaps로 React를 할 수 있다니.
htm 운반이 필요 없는 문자열로 JSX를 쓴 포장을 사용한 것 같다.
보기만 해도 징그럽지만 안 먹는 것도 있어서 만져봤어요.
rails new
아무튼 아주 평범하다rails new.
Ruby 버전은 3.0.3입니다.
적절한 루트 페이지 준비
./bin/rails generate controller home index
routes.rb
Rails.application.routes.draw do
  root 'home#index'
end
htm 및 react 설정
여기서부터 본공연인데.
영상과 조금 다른 일을 했지만 큰 차이는 없었어요.
importmaps의 설정입니다.
importmap.rb
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"

pin "htm", to: "https://cdn.esm.sh/v45/[email protected]/es2021/htm.js"
pin "react", to: "https://cdn.esm.sh/v45/[email protected]/es2021/react.js"
pin "react-dom", to: "https://cdn.esm.sh/v45/[email protected]/es2021/react-dom.js"
pin_all_from "app/javascript/components", under: "components"
다음에 준비한components/index.js를 읽습니다.
application.js
import "@hotwired/turbo-rails";
import "controllers";
import "components";
마운트할 루트 div를 준비합니다.
app/views/home/index.html.erb
<div id="root"></div>
htm와react를 연결합니다.
raw라는 이름은 VScode의 플러그인과 일치하기 위해서입니다.
app/javascript/components/raw.js
import { createElement } from "react";
import htm from "htm";

export const raw = htm.bind(createElement);
할로 월드.
app/javascript/components/index.js
import { render } from "react-dom";
import { raw } from "./raw";

render(raw`<h1>hello world</h1>`, document.getElementById("root"));
이 단계에서 화면이 이렇게 보일 거예요.

JSX를 쓰는 건?
문자열
현재로서는 문제가 없다.
카운터 구성 요소 추가
어쨌든 나는 매우 간단한 계수기 부품을 추가할 것이다.
영상은class component를 사용했지만 hooks도 갈 수 있습니다.
app/javascript/components/Counter.js
import { useState } from "react";
import { raw } from "./raw";

export function Counter() {
  const [num, setNum] = useState(0);

  return raw`
    <div>
      <button onClick=${() => setNum(num + 1)}>+</button>
      ${num}
    </div>
  `;
}
변수 전개 방식이 좀 바뀌었네.
라우에게 맡긴 것이 문자열이기 때문에 자연히 이렇게 되었다.
app/javascript/components/index.js
import { render } from "react-dom";
import { raw } from "./raw";
import { Counter } from "./Counter";

render(
  raw`
    <h1>hello world</h1>
    <${Counter} />
  `,
  document.getElementById("root")
);
<${Counter} />흑...
드디어 됐어.
일반적인 JSX와 달리 자체 제작 구성 요소의 호출 방법과 중괄호 앞에 $ 정도를 넣으세요.

useState도 열심히 일하고 있어요.
VScode 확장 기능
만약 VScodelit-html의 확장 기능을 사용한다면 JSX는 정상적으로 쓸 수 있을 것이다.lit-html.tags 옵션이 무효인 것은 옥상의 하자입니다.)

문법 하이라이트도 효과가 있다.
Proops 시도
프로포즈를 전달하기 위해 특별한 의미가 없는 구성 요소를 추가했습니다.
app/javascript/components/RenderNum.js
import { raw } from "./raw";

export function RenderNum({ num }) {
  return raw`
    <div>${num}</div>
  `;
}
app/javascript/components/Counter.js
import { useState } from "react";
import { raw } from "./raw";
import { RenderNum } from "./RenderNum";

export function Counter() {
  const [num, setNum] = useState(0);

  return raw`
    <div>
      <button onClick=${() => setNum(num + 1)}>+</button>
      <${RenderNum} num=${num} />
    </div>
  `;
}
그냥 줄 수 있어.
외부 React 패키지를 사용해 보십시오.
이거 못하면 너무 힘들어.
해볼게react-countup.
config/importmap.rb
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"

pin "htm", to: "https://cdn.esm.sh/v45/[email protected]/es2021/htm.js"
pin "react", to: "https://cdn.esm.sh/v45/[email protected]/es2021/react.js"
pin "react-dom", to: "https://cdn.esm.sh/v45/[email protected]/es2021/react-dom.js"
pin "react-countup", to: "https://cdn.esm.sh/v45/[email protected]/es2021/react-countup.js"
pin_all_from "app/javascript/components", under: "components"
app/javascript/components/index.js
import { render } from "react-dom";
import { raw } from "./raw";
import { Counter } from "./Counter";
import CountUp from "react-countup";

render(
  raw`
    <h1>hello world</h1>
    <${Counter} />
    <${CountUp} end={100} />
  `,
  document.getElementById("root")
);

아...Invalid hook call. Hooks can only be called inside of the body of a function component. 그런 것 같아요.
방법이 다른지 안 되는지 판단할 수 없어 어쨌든 포기했다.
상세하고 부드러운 사람 모집입니다.
감상
취미가 좀 있지만 의외로 할 수 있어요.
(아직 안 써봤지만) 스틸러스가 매우면 이걸로 해도 돼요?
특히 외부 리액트 포장을 이용할 수 있다면 매력적이지 않겠나.
검증에 사용되는 코드는 github에 있습니다.

좋은 웹페이지 즐겨찾기