SolidJS - React의 대안?

Solidjs는 무엇입니까?



오늘 인터넷에서 프런트엔드용 고성능 프레임워크를 검색하다가 solidjs 간단하고 성능이 뛰어난 반응형 빌드 사용자 인터페이스를 찾았습니다.

프로젝트 github 링크는 here입니다.

시작하다



vite-plugin-solid을 사용하여 시작할 수 있는 동안:

npx degit solidjs/templates/js my-solid-project
cd my-solid-project
npm install # or pnpm install or yarn install
npm run start # starts dev-server with hot-module-reloading
npm run build # builds to /dist


vite 관련 플러그인을 수동으로 설치할 수 있습니다.

# with npm
npm install -D vite vite-plugin-solid babel-preset-solid
npm install solid-js

# with pnpm
pnpm add -D vite vite-plugin-solid babel-preset-solid
pnpm add solid-js

# with yarn
yarn add -D vite vite-plugin-solid babel-preset-solid
yarn add solid-js


다음과 같이 vite.config.js에서 찾을 수 있는 모든 것을 설치한 후

// vite.config.ts
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';

export default defineConfig({
  plugins: [solidPlugin()],
});


일부 데모에 사용하는 코드는 다음과 같습니다.


import logo from "./logo.svg";
import styles from "./App.module.css";

import {
  createEffect,
  createSignal,
  createMemo,
  createResource,
  Show,
  Switch,
  Match,
} from "solid-js";
import { render, Portal, Dynamic } from "solid-js/web";
const fetchUser = async (id) =>
  (await fetch(`https://swapi.dev/api/people/${id}/`)).json();

const User = () => {
  const [userId, setUserId] = createSignal();
  const [user] = createResource(userId, fetchUser);

  return (
    <>
      <input
        type="number"
        min="1"
        placeholder="Enter Numeric Id"
        onInput={(e) => setUserId(e.currentTarget.value)}
      />
      <span>{user.loading && "Loading..."}</span>
      <div>
        <pre>{JSON.stringify(user(), null, 2)}</pre>
      </div>
    </>
  );
};

function fibonacci(n) {
  if (n <= 1) return 1;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

function Modal() {
  return (
    <div class="container">
      <Portal>
        <div class="popup">
          <h1>Popup</h1>
          <p>Some text you might need for something or other.</p>
        </div>
      </Portal>{" "}
    </div>
  );
}

function Compare() {
  const [x] = createSignal(7);

  return (
    <Switch fallback={<p>{x()} is between 5 and 10</p>}>
      <Match when={x() > 10}>
        <p>{x()} is greater than 10</p>
      </Match>
      <Match when={5 > x()}>
        <p>{x()} is less than 5</p>
      </Match>
    </Switch>
  );
}

function Cats() {
  // <For each={}> to handle for loop, it updates or moves DOM rather than recreating them
  const [cats, setCats] = createSignal([
    { id: "J---aiyznGQ", name: "Keyboard Cat" },
    { id: "z_AbfPXTKms", name: "Maru" },
    { id: "OUtn3pvWmpg", name: "Henri The Existential Cat" },
  ]);
  return (
    <For each={cats()}>
      {(cat, i) => (
        <li>
          <a
            target="_blank"
            href={`https://www.youtube.com/watch?v=${cat.id}`}
            style={{ color: "white" }}
          >
            {i() + 1}: {cat.name}
          </a>
        </li>
      )}
    </For>
  );
}
// wrong naming would not work here
function Btn() {
  const [loggedIn, setLoggedIn] = createSignal(true);
  const toggle = () => setLoggedIn(!loggedIn());

  return (
    <Show when={loggedIn()} fallback={<button onClick={toggle}>Log in</button>}>
      <button onClick={toggle}>Log out</button>
    </Show>
  );
}

function Counter() {
  const [count, setCount] = createSignal(0);
  const fib = createMemo(() => fibonacci(count()));
  const doubleCount = () => count() * 2;
  createEffect(() => {
    console.log("the count is: ", count());
  });
  return (
    <>
      <button onClick={() => setCount(count() + 1)}>Click Me</button>
      {count()} <br />
      {doubleCount()} <br />
      fib: {fib()}
    </>
  );
}

function App() {
  return (
    <div class={styles.App}>
      <p>Counter demos how signal and createEffect / createMemo work</p>
      <Counter /> <p>Btn demos how simple conditional works in Solid</p>
      <Btn />
      <p>Cats demos how list rendering works using For tag </p>
      <Cats />
      <p>Compare demos how switch and match work</p>
      <Compare />
      <p>Modal demos how Portal works </p>
      <Modal />
      <p>Async demos </p>
      <User />
    </div>
  );
}

export default App;



let's take a look one by one, this article will update



항목 및 구성 요소


  • 내가 solidjs를 좋아하는 한 가지는 classclass 대신 className라는 점이며, 나머지 대부분은 jsx 작성에 반응하는 것과 동일합니다
  • solidjs는 render() 함수를 사용하여 렌더링하고 2개의 인수를 사용하며 첫 번째는 함수이고 두 번째는 컨테이너입니다

  • 신호 및 효과/메모


    signalssolidjs에서 가장 기본적인 반응형 프리미티브이며 시간이 지남에 따라 변경되는 모든 JS 객체가 될 수 있는 단일 값을 추적합니다.
    createSignal 함수는 한 쌍의 함수를 2개 요소 배열로 반환합니다. 게터와 세터는 기본적으로 useState를 생각나게 합니다.

    여기서 우리는 Counter를 정의하고, count를 신호로 정의하고, 여기에서 파생된 두 개의 신호, 즉 fibdoubleCount를 정의합니다.

    버튼을 클릭하여 숫자를 추가하면 doubleCountfib가 모두 업데이트됩니다.

    function Counter() {
      const [count, setCount] = createSignal(0);
      const fib = createMemo(() => fibonacci(count()));
      const doubleCount = () => count() * 2;
      createEffect(() => {
        console.log("the count is: ", count());
      });
      return (
        <>
          <button onClick={() => setCount(count() + 1)}>Click Me</button>
          {count()} <br />
          {doubleCount()} <br />
          fib: {fib()}
        </>
      );
    }
    

    createEffect solidjs에서 함수로 효과를 생성하는 데 사용됨

    이 효과는 함수 실행 중에 읽은 모든 신호를 자동으로 구독하고 신호 중 하나가 변경되면 반환합니다. --> Vue와 비슷합니다watch.

    흐름, 보여주기



    JSX를 사용하면 JS를 사용하여 템플릿의 논리 흐름을 제어할 수 있지만 여기에서 가상 DOM을 사용하지 않는 경우 Array.prototype.map를 사용하면 업데이트할 때마다 모든 DOM 노드가 낭비적으로 다시 생성됩니다.

    간단한 조건부 표시를 위해 solidjs는 Show 태그를 제공합니다.

    <Show
      when={loggedIn()}
      fallback={<button onClick={toggle}>Log in</button>}
    >
      <button onClick={toggle}>Log out</button>
    </Show>
    

    fallback 소품은 else로 작동하고 when에 전달된 조건이 참이 아닌 경우 표시

    예:

    // wrong naming would not work here
    function Btn() {
      const [loggedIn, setLoggedIn] = createSignal(true);
      const toggle = () => setLoggedIn(!loggedIn());
    
      return (
        <Show when={loggedIn()} fallback={<button onClick={toggle}>Log in</button>}>
          <button onClick={toggle}>Log out</button>
        </Show>
      );
    }
    


    For, 색인, 전환, 일치



    더 복잡한 조건문에 도달하면 제공해야 합니다.

    목록을 렌더링하기 위해 위에서 언급한 이유 때문에(여기에는 가상 DOM이 없음) solidjs는 여기에 For 태그도 제공합니다.

    이 예에서는 콘텐츠가 포함된 인덱스 목록을 렌더링합니다.

    function Cats() {
      // <For each={}> to handle for loop, it updates or moves DOM rather than recreating them
      const [cats, setCats] = createSignal([
        { id: "J---aiyznGQ", name: "Keyboard Cat" },
        { id: "z_AbfPXTKms", name: "Maru" },
        { id: "OUtn3pvWmpg", name: "Henri The Existential Cat" },
      ]);
      return (
        <For each={cats()}>
          {(cat, i) => (
            <li>
              <a
                target="_blank"
                href={`https://www.youtube.com/watch?v=${cat.id}`}
                style={{ color: "white" }}
              >
                {i() + 1}: {cat.name}
              </a>
            </li>
          )}
        </For>
      );
    }
    

    SwitchMatch는 상호 배타적인 결과가 2개 이상인 조건문을 처리해야 할 때 사용됩니다.

    function Compare() {
      const [x] = createSignal(7);
    
      return (
        <Switch fallback={<p>{x()} is between 5 and 10</p>}>
          <Match when={x() > 10}>
            <p>{x()} is greater than 10</p>
          </Match>
          <Match when={5 > x()}>
            <p>{x()} is less than 5</p>
          </Match>
        </Switch>
      );
    }
    


    타이트하고 깨끗한 코드를 작성하고 싶다면 Dynamic를 사용하여 작성할 수 있습니다.

    <Switch fallback={<BlueThing />}>
      <Match when={selected() === 'red'}><RedThing /></Match>
      <Match when={selected() === 'green'}><GreenThing /></Match>
    </Switch>
    
    # to this 
    
    <Dynamic component={options[selected()]} />
    


    ErrorBoundary, 서스펜스



    UI에서 js 오류를 캡처하고 표시하려는 항목으로 대체할 수 있습니다. 먼저 <Broken />를 정의합니다.

    const Broken = (props) => {
      throw new Error("Oh No");
      return <>Never Getting Here</>
    }
    


    그런 다음 사용하십시오.

      <div>Before</div>
          <ErrorBoundary fallback={err => err}>
            <Broken />
          </ErrorBoundary>
          <div>After</div>
    




    수명 주기(onMount, onCleanup, onError)



    solidjs에는 수명 주기 API가 거의 없습니다.

    onMount(async () => {
      const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);
      setPhotos(await res.json());
    });
    
    const timer = setInterval(() => setCount(count() + 1), 1000);
    onCleanup(() => clearInterval(timer));
    


    결론



    글쎄요, solidjs 재미있어 보이지만 Vue3도 훨씬 더 풍부한 생태계 및 기타 항목으로 판매하는 것을 할 수 있는 것 같습니다. 나는 개인적으로 여전히 Vue를 고수합니다.

    좋은 웹페이지 즐겨찾기