React 갈고리로 설계와 논리의 결합을 실현하다
20745 단어 reactdesignjavascript
이 글을 쓰는 생각은 React의 날짜 선택기 구성 요소를 위한 라이브러리를 찾으려고 할 때 나온 것입니다.대부분의 소프트웨어 패키지는 같은 소프트웨어 패키지에 응용 프로그램 논리와 디자인을 포함하는데 만약에 맞춤형 제작이 필요하다면 프로젝트 측에 해커 해결 방안이 나타날 수 있다.
이것도 우리 프로젝트에서 볼 수 있듯이, 우리 프로젝트에서 디자인과 논리를 밀접하게 결합하면, 어떠한 새로운 특성을 만들어서 구성 요소의 크기를 증가시킬 수 있다.이것은 종종 기능이 풍부하지만 방대한 구성 요소를 테스트하고 모든 구성 요소가 정상적으로 작동하도록 확보하기 어렵다.
무상태 구성 요소 작성
논리와 디자인의 결합은 무상태 구성 요소를 만드는 것부터 시작되며, 이 구성 요소들은 필요한 디자인의 각 부분을 실현하고 있다.
이를 실현하기 위해서, 이 논리로 사용자 정의 옵션 구성 요소를 만듭니다.디자인 부분에 대해 우리는 두 개의 부품이 있을 수 있다.TabItem에는 탭을 둘러싸는 개별 탭이 표시됩니다.
interface TabItemProps {
onClick: (value: String) => void,
isSelected : Boolean,
children: String
}
const TabItem = ({
onClick,
isSelected,
children,
}: TabItemProps) => (
<button onClick={() => onClick(children)} className={isSelected ? "selected"}>
{children}
</button>
)
interface TabContainerProps {
children: React.ReactNode
}
const TabContainer = ({ children }: TabContainerProps)=> (
<div>
{children}
</div>
)
이러한 무상태 구성 요소를 만들 때, 기능을 더 작은 독립 용기로 나누는 방법에 중점을 두어야 한다.이 점에 대한 규칙이 많지 않고 해결 방안이 많기 때문에 가장 유익한 방법은 일치를 유지하는 것이다.구성 요소 내부에 어떤 상태도 포함되지 않아도, 사용자 체험에 필요한 작업을 수행할 수 있도록 주어진 속성에 따라 논리를 저장합니다.해결 방안에 따라 구성 요소는 논리를 저장할 수도 있고 논리에서 파생된 상태만 저장할 수도 있습니다.
예를 들어, TabItem에는 명확한 설명 용례가 있는 isSelected 속성이 있습니다.활동 속성도 이를 통해 더욱 통용되고 논리적인 부분에서 하나의 옵션 카드가 언제 활동 상태에 있는지를 결정할 수 있는 권한을 부여할 수 있다.
우리는 무상태 구성 요소가 그들의 요구에 완전히 부합되는지 확인하기 위해 무상태 구성 요소를 위한 테스트를 만들어야 한다.내부 논리가 포함되지 않기 때문에 테스트는 훨씬 쉽다. 왜냐하면 우리는 모든 상태가 예상대로 작동하도록 확보하기만 하면 되기 때문이다.이것은 스냅샷 테스트(DOM 또는 화면 캡처)와Storybooks storyshots 또는Chromatic 등 로컬 도구를 사용하여 실현할 수 있다.
무상태 구성 요소에 갈고리 추가
이 무상태 구성 요소들이 협동하여 작업을 하기 위해서, 우리는 모든 필요한 논리를 처리하기 위해 갈고리를 만들 것이다.상태를 포함할 필요는 없지만 모든 데이터와 조작을 구성 요소에 전달해야 합니다.
interface Tab {
name: String,
value: String,
isSelected: Boolean,
isDisabled: Boolean?
}
interface useTabHook {
tabList: Tab[],
onChangeTab: (value: String) => void
content: (selectedTab: String) => any
}
const useTabs = (tabs : Tab[], content: any) : useTabHook => {
const [selectedTab, setSelectedTab] = React.useState(tabs[0]?.value)
return {
tabList: (tabs || []).map(item => ({ ...item, isSelected: selectedTab === item?.value })),
onChangeTab: (value) => setSelectedTab(value),
content: content(selectedTab)
};
}
갈고리의 범위는 주로 논리를 포함하고 스타일과 관련된 모든 변수(유명 또는 내연 스타일)를 배제해야 한다.때때로 갈고리에서 온 스타일에 접근성이나 실용 프로그램 속성을 추가하는 것은 의미가 있을 수 있습니다.갈고리는 일부 데이터가 직접 값을 되돌려주더라도 구성 요소가 필요로 하는 모든 외부 데이터와 조작을 사용해야 한다.모든 필요한 속성을 갈고리에 포함시키면 사용이 더욱 쉽다. 데이터가 어디에서 왔는지 알고 숨길 필요가 없기 때문이다.
갈고리는 모든 데이터 변환과 동작 실행을 처리하기 때문에 개발자의 우호적인 API와 조합 가능한 내부 부품이 성공의 관건이다.구성 요소가 비교적 간단할 때 (예: 예시) 뚜렷하지 않을 수도 있지만, 복잡성이 증가하면 API에 대한 노력은 큰 차이가 생길 수 있다.
우리는 데이터 변환과 조작에만 관심을 가지기 때문에 테스트가 더욱 직접적이다.DOM을 중간층으로 사용할 필요는 없지만, 우리는 모든 작업을 할 수 있으며, 입력과 출력 속성만 걸면 된다.
갈고리에 대한 테스트를 간소화할 수 있는 react-hooks-testing-library라는 라이브러리도 있다.
무상태 구성 요소와 갈고리 조합
마지막으로, 우리는 갈고리로 정의된 방식으로 무상태 구성 요소를 사용하는 구성 요소를 만들어서 논리와 디자인을 결합시켜야 한다.
interface TabsProps {
tabs: Tab[];
children: React.ReactNode;
}
const Tabs = ({ tabs, children }: TabsProps) => {
const { tabList, onChangeTab, content } = useTabs(tabs, children)
return (
<React.Fragment>
<TabContainer>
<React.Fragment>
{tabList.map(({ name, ...tab }) => (
<TabItem {...tab} onClick={onChangeTab}>
{name}
</TabItem>
))}
</React.Fragment>
</TabContainer>
{children}
</React.Fragment>
)
}
무상태 모듈과 갈고리는 모두 철저한 테스트를 거쳤기 때문에 메인 모듈은 이 두 요소가 정상적으로 작동하는지 확인하기 위한 통합급 테스트만 필요합니다.우리의 예시에서, 이 테스트들은 옵션 구성 요소가 정확하게 나타나고, 키 흐름이 예상한 대로 작동하도록 확보할 것이다.이런 방법의 장점과 단점
해체는 테스트를 더욱 쉽게 한다. 왜냐하면 우리는 디자인과 논리 방면에서 정확한 도구와 실천을 사용할 수 있기 때문이다.논리 테스트는 특정 작업 후에 출력을 검사하는 것에 관한 것이지만, 디자인 테스트는 DOM/렌더링 구성 요소를 검사하는 것이 더 많다.이러한 테스트는 상대적으로 다른 도구와 테스트 실천을 필요로 하기 때문에 결합으로 인해 그것들을 혼합하면 더 많은 테스트를 만들 수 있을 뿐만 아니라 이 두 가지 테스트 유형에 불필요한 작업을 만들 수 있다.
결합 구성 요소로 처리할 수 있는 것들을 테스트할 때 진정한 장점은 디자인이나 논리에 대한 새로운 요구가 있고 이러한 요구가 이미 제정된 요구와 일치하지 않을 때이다.예를 들어 여러 제품이 같은 코드 라이브러리를 사용하고 디자인이나 논리에 대한 요구가 약간 다를 수 있습니다.
예를 들어 우리의 예에서 같은 유형의 옵션 논리를 가지지만 디자인이 다른 제품이 있다면 갈고리 부분을 다시 사용할 수 있다.만약 옵션 중 하나에 비활성화된 갈고리가 필요하다면, 현재 갈고리 주위에 비활성화된 논리를 가진 새로운 갈고리를 조합해서 갈고리를 확장할 수 있습니다.
// Additional TabItem component with disabled state
const DisabledTabItem = ({
onClick,
isSelected,
isDisabled,
children,
value
}): {
onClick: (MouseEvent<HTMLButtonElement>) => void,
isSelected : Boolean,
isDisabled: Boolean,
children: String,
value: String
} => (
<button onClick={onClick} value={value} disabled={isSelected}>
{children}
</button>
)
// Extented hook to handle disabled state
const useDisabledTabs = (input) => {
const content = useTabs(input)
return {
...content,
onChange: (props) => {
const tab = input.tabs.find((item) => item.value === props.target.value && item.isDisabled)
if (tab !== undefined) {
content.onChange(props)
}
},
}
}
// Combining extra features
const TabsWithDisable = ({ tabs, children }) => {
const { tabList, onChangeTab, content } = useDisabledTabs({
tabs,
content: children,
})
return (
<React.Fragment>
<TabContainer>
{tabList.forEach(({ text, ...tab }) => (
<DisabledTabItem {...tab} onClick={onChangeTab}>
{text}
</DisabledTabItem>
))}
</TabContainer>
{content}
</React.Fragment>
)
}
이 두 가지 상황에서 다시 사용할 수 있는 부분은 모두 쉽게 얻을 수 있으며, 새 코드를 다시 테스트하기만 하면 된다.이것은 이미 만들어진 구성 요소에 대한 돌파적인 변경이 없기 때문에 개발 속도가 크게 빨라졌다.물론 이런 우세는 공짜가 아니다.논리와 디자인의 결합을 기존 코드를 바탕으로 코드를 작성하여 의존성을 높일 수 있다.만약 기초 의존 관계가 최종적으로 파괴적인 변경을 필요로 한다면, 높은 의존 관계 트리도 개발을 더디게 할 것이다.높은 의존 트리는 전체 국면을 보기 어려워지기 때문에, 최상위 층을 구축하고 현재 코드를 재구성하는 데 균형을 잡아야 한다.
예.
나는 이런 방법이 최근에 더욱 많은 동력을 얻었고, 상당히 좋은 생산 준비 소프트웨어 패키지를 사용할 수 있다는 것을 보고 매우 기뻤다.
날짜 선택기 연결
내가 본 첫 번째 이 패키지는 @datepicker-react/hooks였다.디자인 스타일의 패키지도 있지만 고리 부분은 따로 사용할 수 있습니다.
Adobe 반응 스펙트럼
React Spectrum 갈고리 라이브러리를 통해 이 점을 한층 더 실현했고 갈고리 라이브러리는 가장 흔히 볼 수 있는 접근 가능성과 논리를 제공했다.
만약 당신이 더 많은 유사한 정보를 알고 있다면, 평론을 써 주세요.나는 이런 소포가 더 있는지 매우 알고 싶다.
요약
결합 설계와 논리는 갈고리와 무상태 구성 요소를 통해 완성할 수 있다.이로써 이미 작성된 논리나 디자인을 바탕으로 새로운 구성 요소를 만들고 논리와 디자인을 각각 테스트할 수 있다.
Reference
이 문제에 관하여(React 갈고리로 설계와 논리의 결합을 실현하다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/akirautio/decouple-design-from-the-logic-with-react-hooks-6fd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)