단지 우호적인 알림일 뿐입니다. React는 실제로는 자바스크립트만 있는 것이 아닙니다. (기능 구성 요소를 끼워넣지 마십시오.)

17961 단어 javascripta11yreact
이것은 내가 쓴 첫 번째 React에 관한 블로그 글이다. 비록 영국의 최첨단 취업 시장 때문에 나는 매일 그것을 사용하고 싶지 않다.나는 이런 유행하는 틀에 대해 이야기하는 것을 후회할지도 모른다. 오, 이것은 틀이다😉.
최근에 나는 사이드바 구성 요소의 애니메이션 슬라이드를 쓰고 있는데, 그것을 켜서 페이지의 다른 구성 요소의 추가 세부 사항을 표시할 수 있다.나의 목표 중 하나는 상세한 정보 창을 열 때 페이지의 옵션과 초점 순서가 합리적인지 확인하는 것이다. 즉, 나는 초점을 열 때 초점을 훔치고 닫을 때 초점을 원시 단추로 복원하기를 바란다.예를 들어, 버튼을 누른 상태에서 [세부 정보] 패널을 열고 패널을 초점을 맞춘 다음 다시 스페이스바를 사용하여 닫을 수 있습니다.그리고 초점은 원래 단추로 돌아갑니다. "tab"를 누르면 다음 항목으로 이동할 수 있습니다.
다음은 제가 구축하고 있는 간략한 예입니다. HTTP 상태 코드 kitties를 사용하여 this Code sandbox에서 직접 시도해 보겠습니다.

다음은 응용 프로그램의 코드입니다. 이것은 급하게 작성된 HTML입니다. 개선을 통해 실현할 수 있을 것이라고 믿습니다.
import "./styles.css";
import { useState } from "react";
import { Sidebar } from "./Sidebar";
export default function App() {
  const statusCodes = [500, 404, 403, 401, 418, 420, 301, 302, 200, 201, 204];
  const [selectedCode, setSelectedCode] = useState(null);

  const Codes = (
    <ul>
      {statusCodes.map((code) => (
        <li key={code}>
          <button onClick={() => setSelectedCode(code)}>{code}</button>
        </li>
      ))}
    </ul>
  );

  return (
    <div className="App">
      <h1>HTTP Status Cats</h1>
      {Codes}
      <Sidebar
        onClose={() => setSelectedCode(null)}
        ariaLabel={`${selectedCode} status code info`}
        open={Boolean(selectedCode)}
      >
        <h2>{selectedCode}</h2>
        <img
          alt={`Cat demonstrating HTTP status code: ${selectedCode}`}
          src={`https://http.cat/${selectedCode}.jpg`}
        />
      </Sidebar>
    </div>
  );
}
사이드바, 즉'초점 탈취/회복'이 발생한 곳도 있다.
import { useEffect, useRef, useState } from "react";

export const Sidebar = ({ ariaLabel, open, onClose, children }) => {
  const [previousFocus, setPreviousFocus] = useState();
  // now focus inside something, for arguments sake, the close button
  const closeBtnRef = useRef(null);
  useEffect(() => {
    if (open) {
      setPreviousFocus(document.activeElement);
      closeBtnRef?.current?.focus();
    }
    // bit of a hack putting aria label in here so triggers if another option selected.
  }, [open, ariaLabel, closeBtnRef]);

  return (
    <aside aria-label={ariaLabel} aria-hidden={open ? "false" : "true"}>
      <button
        disabled={!open}
        ref={closeBtnRef}
        onClick={() => {
          // restore previous focus
          previousFocus?.focus();
          onClose();
        }}
      >
        Close X
      </button>
      {open && children}
    </aside>
  );
};
이 코드는 정상적으로 작동했다. 그리고 나는 하나의 지점을 바탕으로 하는pr에서 일했다. 나는 새로운 변경 사항을 도입했고 초점 내비게이션이 실패하기 시작했다는 것을 알아차렸다.

Actually, a unit test, which tested the focus interactions started failing which is actually pretty awesome! React Testing Library moved unit testing forward SO MUCH in comparison to Enzyme it's great. If it could only run by default inside a browser instead of Jest, that would be great. By default I mean, commonplace in the industry, i'm sure it's achievable.


위의 예제에서 새 PR에는 위 코드 세그먼트의 Codes 변수와 같은 변수가 추가되었습니다.
const Codes = (
  <ul>
    {statusCodes.map((code) => (
      <li key={code}>
        <button onClick={() => setSelectedCode(code)}>{code}</button>
      </li>
    ))}
  </ul>
);
<h1>HTTP Status Cats</h1>;
{
  Codes;
}
그러나 이는 새로운 내용이 아니라 다음과 같습니다.
const Codes = () => (
  <ul>
    {statusCodes.map((code) => (
      <li key={code}>
        <button onClick={() => setSelectedCode(code)}>{code}</button>
      </li>
    ))}
  </ul>
);
<h1>HTTP Status Cats</h1>;
{
  <Codes />;
}
차이는 매우 미묘하지만 매우 중요하다. Codes을 하나의 함수로 만들어 다른 함수 구성 요소에 끼워 넣은 함수 반응 구성 요소이다.CodesApp의 변수라는 것을 기억하세요.이것은 코드 평가에서 간과되기 쉬운 것이지만, 많은 것을 파괴했다.
다음은 실패의 예: https://codesandbox.io/s/http-status-cats-broken-fiu72?file=/src/App.jsx:508-554

여기서 일어난 일은 리액트가 렌더링할 때마다'앱'구성 요소의 내용을 렌더링하는 것이다. 내부 구성 요소가 기억되지 않거나 리액트가 쓰레기통에 버리고 다시 렌더링만 하기 때문이다.내부에서 DOM 요소를 삭제하고 다시 추가하면 원래 버튼으로 돌아가는 초점 상태가 깨집니다.
코드에서 이 점을 보면 이것은 뚜렷하지 않은 복구이다. 특히 다른 사람의 코드를 볼 때 나는 몇 가지 일을 생각하게 된다.
  • 만약 우리가 좋은 테스트가 없다면 우리는 이것을 발견할 수 있습니까?
  • 몇 달 후, 코드가 머릿속에서 그다지 신선하지 않을 때, 우리는 그 원인을 찾을 수 있습니까?
  • 만약에 React가'순수한Javascript'라면 왜 이렇게 철저하게 Javascript에 포함된 함수와 클립을 만드는 가장 좋은 기능 중 하나를 파괴할 수 있습니까?
  • 왜 이것은 React docs와 기본 피면 규칙의 앞부분과 중부가 아닙니까?
  • 나는 마지막 두 가지에서 몇 가지 발굴을 했다.
    공식 문서에서 내가 찾을 수 있는 유일한 플러그인 함수에 대한 인용은 고전적인 "Rules of Hooks"페이지:Don’t call Hooks inside loops, conditions, or nested functions에서 왔지만 플러그인 구성 요소는 언급하지 않았다.

    As an aside, I love the the fact that the mechanism that React is now mostly entirely based on, "hooks", requires a list of rules to help prevent you from writing "Just JavaScript".


    lint 규칙에 대해 유행하는 eslint-plugin-react-no-unstable-nested-components에는 확실히 사용할 수 있는 규칙이 있는 것 같다. 아마도 나는 우리 팀에게 이렇게 하라고 건의할 것이다.기능 구성 요소를 끼워 넣고 싶을 때,useMemo를 좋아하고 사용하더라도, 물론 더 간단한 코드를 작성하는 것이 좋다.
    제가 흥미로운 점은 코드에서 이렇게 미세한 변화가 무고해 보이면 React 구성 요소의 표현 과정에서 큰 파괴를 초래할 수 있다는 것입니다. 저는 그 중에서 제가 좋은 단원 테스트 집합을 작성했고'상호작용'과'접근성'을 테스트할 수 있다는 것을 알게 되었습니다. 왜냐하면 이런 것들은 후퇴하기 쉽기 때문입니다!
    읽어주셔서 감사합니다!제 작품을 더 많이 읽고 싶으시면 트위터에 팔로우를 해주시거나 원하시면 coffee을 주세요.☕.

    좋은 웹페이지 즐겨찾기