3. 당신이 알아야 할 구성 요소 디자인 모델
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 Router 및 React-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
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
을 만들었습니다.이렇게 하면 Menu
및 MenuItem
구성 요소의 공유 상태가 유지됩니다.선택한 메뉴 항목을 위한 상태도 만들었습니다.이것은 공급자 모드에서처럼 상하문을 업데이트할 수 있도록 합니다. 상하문 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 구성 요소를 구축하는 데 사용되는 각종 디자인 모델을 연구했다.비록 이것은 상세한 목록은 아니지만, 구성 요소를 구축할 때 발생할 수 있는 대부분의 문제에 적용된다.
Reference
이 문제에 관하여(3. 당신이 알아야 할 구성 요소 디자인 모델), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/asayerio_techblog/3-react-component-design-patterns-you-should-know-about-4cj1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)