3. 당신이 알아야 할 구성 요소 디자인 모델

37086 단어 beginnerswebdevreact
작성자Samaila Bala
React는 사용자 인터페이스를 구축하는 데 가장 유행하는 자바스크립트 라이브러리라고 할 수 있는데, 그 원인 중 하나는 비컴파일성이다.React를 하나의 프레임워크로 보든 라이브러리로 보든 개발자가 React 응용 프로그램을 어떻게 구축해야 하는지에 대해 React는 간섭하지 않는 방법을 사용해서 개발자와 개발진이 응용 프로그램을 어떻게 만드는지 자유롭게 결정할 수 있다.서로 다른 팀과 협력하여 서로 다른 React 응용 프로그램을 개발하고 다른 React 응용 프로그램을 연구한 후에 당신은 흔히 볼 수 있는 디자인 모델을 발견할 수 있습니다.
본고에서 우리는 React 응용 프로그램을 구축하는 데 사용되는 세 가지 유행 디자인 모델을 연구할 것이다.

1. 컨테이너 구성 요소 모드 보이기


이것은 Dan Abramov가 창조한 도안이다.이 모드에서 어셈블리는 다음과 같습니다.

  • 표시 구성 요소: UI의 모양을 담당합니다.그것들은 응용 프로그램의 어떤 부분과도 의존 관계가 없어서 데이터를 표시하는 데 사용된다.다음은 목록입니다.
  • const ItemsList = (props) => {
        return (
        <ul>
            {props.items.map((item) => (
            <li key={item.id}>
                <a href={item.url}>{item.name}</a>
            </li>
            ))}
        </ul>
        );
    };
    
    상기 예시에서 우리의 ItemsList 구성 요소는 사용자 인터페이스에 props로 전달된 데이터만 표시한다.렌더링 구성 요소를 무상태 기능 구성 요소라고도 하지만 클래스 구성 요소로 작성할 수도 있고 UI와 관련된 상태를 포함할 수도 있습니다.
    class TextInput extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          value: ""
        };
      }
      render() {
        return (
          <input
            value={this.state.value}
            onChange={(event) => this.setState({ value: event.target.value })}
          />
        );
      }
    }
    
    상기 예시에서 우리는 표시 클래스 구성 요소TextInput를 생성하여 그 상태를 관리한다.

  • 용기 구성 요소: 이미지 구성 요소와 달리 용기 구성 요소는 사물의 작업 방식을 더욱 책임진다.이들은 일반적으로 라이프 사이클 방법과 어셈블리를 나타내는 클래스 어셈블리입니다.그것도 데이터를 얻는 곳이다.
  •  class TvShowsContainer extends React.Component {
          constructor(props) {
            super(props);
            this.state = {
              shows: [],
              loading: false,
              error: ""
            };
          }
          componentDidMount() {
            this.setState({ loading: true, error: "" });
            fetch("https://api.tvmaze.com/schedule/web?date=2020-05-29")
              .then((res) => res.json())
              .then((data) => this.setState({ loading: false, shows: data }))
              .catch((error) =>
                this.setState({ loading: false, error: error.message || error })
              );
          }
          render() {
            const { loading, error, shows } = this.state;
            return (
              <div>
                <h1> Tv Shows </h1>
                {loading && <p>Loading...</p>}
                {!loading && shows && <ItemsList items={shows} />}
                {!loading && error && <p>{error}</p>}
              </div>
            );
          }
        }
    
    위의 예제에서 이 구성 요소를 마운트할 때 API에서 데이터를 가져오는 TvShowsContainer 구성 요소를 생성했습니다.이것은 또한 우리가 이전에 만든 표시 구성 요소 ItemsList 에 데이터를 전달합니다.이런 모델의 장점은 주목점과 구성 요소의 중용성 분리이다.다른 용기 구성 요소는 ItemList 표시 구성 요소를 다시 사용해서 데이터를 표시할 수 있습니다. 왜냐하면 TvShowsListContainer와 밀접하게 결합되지 않기 때문입니다.작업 어플리케이션here를 볼 수 있습니다.
    댄은 이 문제에 대한 자신의 견해를 바꾸었기 때문에, 그가 처음에 이 모델을 창조했기 때문에, 다시는 이런 모델을 보급하지 않겠다고 언급했다.그러나, 이것은 특정한 용례에 매우 유용하다는 것을 발견할 수 있습니다. 이것이 바로 이 목록에서 언급된 것이 관련이 있다고 생각하는 이유입니다.

    2. 공급자 모델


    React 개발상들이 직면한 주요 문제는 기둥 굴착이다.도구 시추는 일종의 장면으로 그 중에서 데이터(도구)는 서로 다른 구성 요소로 전달되어 도구가 필요한 구성 요소에 도달할 때까지 전달된다.아이템 시추는 나쁘지 않지만 관련 부품이 데이터를 공유할 때 문제가 되고 공급자 모드로 가져간다.공급자 모드에서는 React Context 객체 및 Redux 저장소와 같은 데이터를 중앙에 저장할 수 있습니다.그 다음에 상하문에 프로그램/저장을 제공하면 이 데이터를 필요로 하는 모든 구성 요소에 직접 전달할 수 있으며, 구멍을 뚫는 도구가 필요하지 않다.
    웹 응용 프로그램에 암흑 모드를 실현하여 상관없는 구성 요소가 서로 다른 구성 요소에서 터치하는 테마 변경에 응답하도록 상상해 보세요.우리는 공급자 모델을 사용하여 이 점을 실현할 수 있다.주제의 값을 저장하기 위해 React 컨텍스트 객체를 만듭니다.
    import { createContext } from "react";
    const ThemeContext = createContext({
      theme: "light",
      setTheme: () => {}
    });
    export default ThemeContext;
    
    응용 프로그램에서js 파일, 가져온 구성 요소를 ThemeSecontext로 포장합니다.공급자이렇게 하면 서로 다른 어셈블리와 해당 서브어셈블리가 작성된 컨텍스트 객체에 액세스할 수 있습니다.
    import React, { useState, useMemo } from "react";
    import Header from "./Header";
    import Main from "./Main";
    import ThemeContext from "./context";
    import "./styles.css";
    export default function App() {
      const [theme, setTheme] = useState("");
      const value = useMemo(() => ({ theme, setTheme }), [theme]);
      return (
        <ThemeContext.Provider value={value}>
          <div className="container">
            <Header />
            <Main />
          </div>
        </ThemeContext.Provider>
      );
    }
    
    기본적으로 ThemeContext는 무상태이며 업데이트할 수 없습니다.이 문제를 해결하기 위해서 우리는 ThemeContext를 하나의 상태에 연결하고 ThemeContext에 업데이트 함수를 제공하여 상태를 수정할 수 있다.
    구성 요소 ThemeContext에 액세스하려면 React 16.9에서 설명한 useContext 연결을 사용할 수 있습니다.
    import { useContext } from "react";
    import ThemeContext from "./context";
    const Header = () => {
      const { theme, setTheme } = useContext(ThemeContext);
      const toggleTheme = () => {
        if (theme === "dark") {
          setTheme("");
          return;
        }
        setTheme("dark");
        return;
      };
      return (
        <header className={theme === "dark" && "dark"}>
          <h1> Tv Shows </h1>
          <button onClick={toggleTheme}>Toggle Theme</button>
        </header>
      );
    };
    export default Header;
    
    
    import { useContext } from "react";
    import ThemeContext from "./context";
    const Main = () => {
      const { theme } = useContext(ThemeContext);
      return (
        <main className={theme === "dark" && "dark"}>
          <h2>
            {" "}
            {theme === "dark" ? "Dark theme enabled" : "Light theme enabled"}
          </h2>
        </main>
      );
    };
    export default Main;
    
    상하문은 구성 요소 간에 데이터를 전달하는 것을 더욱 쉽게 하지만, 구성 요소의 재사용을 어렵게 하기 때문에 이런 방법을 조심스럽게 사용하는 것을 권장합니다.상기 예시된 작업 응용 프로그램here에 접근할 수 있습니다.프로그램 모드 사용 가능React RouterReact-Redux.

    오픈 소스 세션 재방송


    생산 환경에서 웹 응용 프로그램을 디버깅하는 것은 어렵고 시간도 소모될 수 있다.OpenReplay는 풀스토리, 로그 로켓과 Hotjar의 소스 대체품이다.사용자가 한 모든 것을 감시하고 재방송할 수 있으며, 모든 문제에 대한 응용 프로그램의 표현을 보여 줍니다.
    이것은 브라우저의 검사기를 열고 사용자의 어깨를 보는 것과 같다.
    OpenReplay는 현재 유일하게 사용할 수 있는 오픈 소스 대안입니다.

    즐거움 디버깅, 현대 전단 팀-Start monitoring your web app for free.

    3. 복합 어셈블리 모드


    복합 구성 요소는 상태를 공유하고 공동 작업을 통해 공동 목표를 실현하는 구성 요소이다.하나의 예는 <select><option> HTML 요소입니다.그것들이 결합되었을 때, 그들은 밑에 있는 메뉴를 만들었지만, 자신들은 큰 성과를 거두지 못했다.
    복합 구성 요소 모드는 Ant Design 및 Material UI와 같은 유행하는 React UI 라이브러리에 사용됩니다.다음은 Material UI의 메뉴 구성 요소 구현입니다.
    import * as React from 'react';
    import Menu from '@mui/material/Menu';
    import MenuItem from '@mui/material/MenuItem';
    
    export default function MaterialMenu() {
      return (
        <div>
          <Button> Menu </Button>
          <Menu>
            <MenuItem>Profile</MenuItem>
            <MenuItem>My account</MenuItem>
            <MenuItem>Logout</MenuItem>
          </Menu>
        </div>
      );
    }
    
    만약 복합 구성 요소가 없다면, 우리는 도구를 부모 구성 요소에 전달하고, 부모 구성 요소는 데이터를 서브 구성 요소에 전달해야 한다
    <Menu items={['Profile','My account', 'Logout']} />
    
    위의 내용은 간단해 보이지만 서브어셈블리에 더 많은 도구를 전달하는 데 문제가 발생하기 시작했습니다.예를 들어 기본적으로 선택한 메뉴 항목을 원한다면
    <Menu items={['Profile','My account', 'Logout']} defaultSelected={1} />
    
    수요가 증가함에 따라 구성 요소는 뒤죽박죽이 되어 사용할 수 없게 되었다.복합 구성 요소 모델은 더욱 깨끗한 실현 방법을 제공했다.
    복합 어셈블리 모드 방법을 사용하여 React 어셈블리를 구성할 수 있는 두 가지 방법이 있습니다.
  • React.cloneElement
  • 반응 상하문
  • 다음 예에서 나는 React-context 방법을 사용할 것이다
    import {
      createContext,
      useState,
      useCallback,
      useMemo,
      useContext
    } from "react";
    import "./styles.css";
    const MenuContext = createContext();
    const Menu = ({ children, defaultSelected }) => {
      const [selectedItem, setSelectedItem] = useState(defaultSelected);
      const toggleSelectedItem = useCallback(
        (item) => {
          if (item !== selectedItem) {
            setSelectedItem(item);
            return;
          }
          selectedItem("");
        },
        [selectedItem, setSelectedItem]
      );
      const value = useMemo(
        () => ({
          toggleSelectedItem,
          selectedItem
        }),
        [toggleSelectedItem, selectedItem]
      );
      return (
        <MenuContext.Provider value={value}>
          <menu className="menu">{children}</menu>
        </MenuContext.Provider>
      );
    };
    
    React context API에서 제공하는 MenuContext 함수를 사용하여 Menu 구성 요소로 상하문 대상 createContext 을 만들었습니다.이렇게 하면 MenuMenuItem 구성 요소의 공유 상태가 유지됩니다.선택한 메뉴 항목을 위한 상태도 만들었습니다.이것은 공급자 모드에서처럼 상하문을 업데이트할 수 있도록 합니다. 상하문 API는 디자인상 무상태이기 때문입니다.
    다음 단계에서는 MenuItem 구성 요소를 구성합니다.
    const useMenuContext = () => {
      const context = useContext(MenuContext);
      if (!context) {
        throw new Error(
          "Menu item component cannot be used outside the Menu component."
        );
      }
      return context;
    };
    const MenuItem = ({ value, children }) => {
      const { toggleSelectedItem, selectedItem } = useMenuContext();
      return (
        <button
          onClick={() => toggleSelectedItem(value)}
          id={`${value}-menu-item`}
          className={`menu__item ${selectedItem === value && "active"}`}
        >
          {children}
        </button>
      );
    };
    
    메뉴 구성 요소 밖에서 MenuItem이 사용되는지 확인하는 데 사용할 사용자 정의 갈고리useMenuContext를 만드는 것입니다. 이 경우 오류가 발생합니다.그런 다음 메뉴 구성 요소의 공유 상태를 사용하여 메뉴 항목을 생성하여 선택한 메뉴 항목에 적용할 스타일을 확인하고 메뉴 항목을 클릭할 때 선택 항목을 변경합니다.
    마지막으로 App 구성 요소에서 이러한 구성 요소를 연결합니다.
    export default function App() {
      return (
          <Menu defaultSelected="My account">
            <MenuItem value="Profile">Profile</MenuItem>
            <MenuItem value="My account">My account</MenuItem>
            <MenuItem value="Logout">Logout</MenuItem>
          </Menu>
      );
    }
    
    전체 응용 프로그램을 볼 수 있습니다 here

    결론


    본고에서 우리는 확장 가능하고 다시 사용할 수 있는React 구성 요소를 구축하는 데 사용되는 각종 디자인 모델을 연구했다.비록 이것은 상세한 목록은 아니지만, 구성 요소를 구축할 때 발생할 수 있는 대부분의 문제에 적용된다.

    좋은 웹페이지 즐겨찾기