사용자 인터페이스용 제네릭
15284 단어 reactgenericstypescriptfunctional
기본적으로 TypeScript가 이것을 잘 처리한다면:
interface Recipe {
title: string
description: string
}
type Recipes = Array<Recipe>
그런 다음 React와 같은 TypeScript 친화적인 프런트엔드 프레임워크는 확실히 다음을 수행할 수 있습니다.
// We get to RecipeEditorProps later in the post
const RecipeEditor: React.FC<RecipeEditorProps> = () => (
<div>
{/* TBA */}
</div>
)
const RecipeListEditor: React.FC<RecipeListEditorProps> = () => (
<div>
{/* Some abstraction involving <RecipeEditor/> */}
</div>
)
tldr here is a CodeSandbox을 보고 싶은 사람들을 위한 것입니다.
리소스를 담당하는 구성 요소를 가져 와서 리소스 목록을 처리하는 구성 요소로 바꾸는 현명한 추상화는 무엇입니까? 더 나은 단어가 없기 때문에 이를 일반 UI라고 부르겠습니다. 특정 불특정 유형으로 구성된 구조에서 작동하는 것입니다.
FP enthusiasts might get excited about fancier names like functor UIs or UI lifting, but I will hold off on those for the time being.
레시피 편집기
레시피 편집을 담당하는 구성 요소는 다음과 같습니다.
interface RecipeEditorProps {
value: Recipe
onChange: (newRecipe: Recipe) => void
}
const RecipeEditor: React.FC<RecipeEditorProps> = (props) => (
<div>
<input
value={props.value.title}
onChange={(ev: ChangeEvent<HTMLInputElement>) => {
props.onChange({
...props.value,
title: ev.target.value
});
}}
/>
<input
value={props.value.description}
onChange={(ev: ChangeEvent<HTMLInputElement>) => {
props.onChange({
...props.value,
description: ev.target.value
});
}}
/>
</div>
);
이를 통해controlled component 부모가 문제의 리소스를 관리할 수 있으므로 구성 요소 계층 구조에서 상태를 충분히 유연하게 관리할 수 있습니다.
목록으로 결합
이 간단한 편집기를 기반으로 리소스 목록을 만들 수 있습니다. 리소스 목록을 매핑하고 변경 이벤트를 연결하여 올바른 인덱스에서 목록을 (불변하게) 업데이트하고 일부 삭제 버튼을 사용하여 마무리할 수 있습니다. 여기에 몇 가지 코드를 추가할 수 있지만 그 시점에서 더미에 또 다른 React todo 목록 튜토리얼을 추가했습니다.
대신 노드 내부에 무엇이 있는지 신경 쓰지 않는 목록 관리자 구성 요소를 살펴보겠습니다.
일반 목록 편집기 추상화
이 추상
ListEditor
구성 요소는 리소스 편집기 구성 요소를 소품으로 사용하고 나머지 작업을 수행합니다. 다음은 이러한 구성 요소의 소품에 대한 몇 가지 유형 정의입니다.export interface Props<T> {
values: Array<T>;
onChange: (newValues: Array<T>) => void;
newValue: () => T;
newValueLabel?: string;
Editor: React.FC<EditorProps<T>>;
}
// The props for the item editor, parameterized by T
export interface EditorProps<T> {
value: T;
onChange: (newValue: T) => void;
}
이 시점에서 모든 것은
T
로 매개변수화되며 나중에 Recipe
, User
등으로 채울 수 있습니다. values
및 onChange
외에도 구성 요소에는 몇 가지 주변 소품이 필요합니다. 추가 버튼을 클릭할 때 새 값을 생성하고 해당 버튼에 포함되어야 하는 레이블입니다.구현은 대략 다음과 같습니다.
function ListEditor<T>(props: Props<T>) {
return (
<div>
<div>
{props.values.map((item, index) => (
<div>
<props.Editor
value={item}
onChange={(newItem) => {
// Use a helper to immutably change item at an index
props.onChange(setAt(index, newItem, props.values));
}}
/>
<button
onClick={() => {
// Use a helper to immutably remove an item at an index
props.onChange(removeAt(index, props.values));
}}
>
Delete
</button>
</div>
)}
</div>
<button
onClick={() => {
props.onChange([...props.values, props.newValue()]);
}}
>
{props.newValueLabel || "Add new"}
</button>
</div>
);
}
마지막으로 적절한 소품을 사용하여
<props.Editor />
인스턴스를 인스턴스화하고 이 구성 요소가 사용되는 모든 위치에서 일관되게 보이는 추가 및 삭제 버튼과 같은 모든 주변 UI를 추가합니다.평화롭게 UX 상품 추가
이제 일반 목록 편집기 구성 요소가 있으므로 코드베이스의 모든 단일 목록 편집기에 전파된다는 것을 알고 멋진 UX 기능을 추가할 수 있습니다.
CodeSandbox에서 레시피 목록과 사용자 목록 모두에 대해 간단한 재정렬을 허용하도록
react-beautiful-dnd
를 추가했습니다. 개별 편집자는 자신이 밀리고 있다는 사실을 결코 알지 못했습니다 🤓.결론
이것으로 무엇을 할 수 있습니까? 나는 패턴이 가져오기 가능한 패키지의 일종으로 이치에 맞지 않는다고 생각합니다. 여전히 스타일이 지정된 UI 코드와 상당히 결합되어 있으며 분리하면 멋진 사용자 지정 후크, 더 많은 사용자 지정 구성 요소 소품 또는 함수를 자식으로 사용할 수 있습니다. . 프로젝트에서 수십 줄의 코드를 설정하고 필요에 맞게 사용자 지정하는 것이 더 나을 것이라고 생각합니다.
아마도 더 중요한 것은 사물 자체가 무엇인지 알 필요 없이 사물 집합을 관리하는 구성 요소라는 일반적인 개념일 것입니다. 이러한 종류의 분리 덕분에 complex projects well beyond lists에 대한 유지 관리 작업 시간이 많이 절약되었습니다. 여러분에게도 도움이 되었기를 바랍니다!
Reference
이 문제에 관하여(사용자 인터페이스용 제네릭), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/peterszerzo/generics-for-user-interfaces-hak텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)