React 내부 상태를 React가 아닌 곳에서 변경하기

리액트가 아니지만 같은 어플리케이션 내에 존재하는 곳에서 특정 리액트 컴포넌트의 상태를 변경하고 싶다면 어떻게 할까요?
2023.03.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

리액트가 아니지만 같은 어플리케이션 내에 존재하는 곳에서 특정 리액트 컴포넌트의 상태를 변경하고 싶다면 어떻게 할까요?

해봅시다

간단한 카운터가 있습니다. 카운트 상태를 가지고 클릭하면 카운트가 증가하는 형태입니다.

import { useState } from "react";

export let outsider = () => {};

export default function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount((prev) => prev + 1);
  };

  outsider = () => {
    setCount((prev) => prev + 1);
  };

  return (
    <div>
      <button onClick={handleClick}> 리액트 안에서</button>
      <div>{count}</div>
    </div>
  );
}

중간에 outsider 라는 함수가 보입니다. 외부에서 호출하기 위해서 선언은 컴포넌트 바깥에서 해줍니다.

outsider가 호출되면 위 컴포넌트의 카운트가 증가시키는 형태인데요. 진짜 증가할까요? 해봅시다.

index.html에서 버튼 태그를 생성해줍니다.

<button id="outsider-button">리액트 바깥에서</button>

생성된 버튼 태그를 찾아서 카운터 컴포넌트에서 불러온 outsider 함수를 이벤트로 등록해줍시다.

import { outsider } from "./Counter";

export default function Outsider() {
  const outsiderButton = document.getElementById("outsider-button");
  if (outsiderButton)
    outsiderButton.addEventListener("click", () => outsider());

  return;
}

그리고 마지막으로 위 Outsider 함수를 어플리케이션이 시작하는 지점에서 호출해줍시다.

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";
import Outsider from "./Outsider";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement!);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

Outsider();

왜 작동하는 걸까요?

ES 모듈에서는 모듈 내의 값을 다른 모듈에서 사용하게 되면 내보낸 쪽의 모듈 내의 값이 변경하는 특징을 가지고 있습니다. 이러한 형태를 라이브 바인딩이라고 합니다.

이 라이브 바인딩을 이용하여서 리액트 외부에서 리액트의 상태를 변경 할 수 있습니다.

마무리

자주 사용될 패턴은 아니지만, 알아두면 한번쯤 쓰지 않을까요?

참고

https://simbathesailor.dev/how-to-trigger-react-components-from-outside-react/ https://stackoverflow.com/questions/52211309/what-does-it-mean-by-live-bindings