#1. [shadcn-chat] 正しいインターフェース継承を通じた textArea コンポーネントの合成文字処理の改善
1. 課題
shadcn-chatが提供するChatInputコンポーネントは、`TextAreaをさらに抽象化した高次コンポーネント`です。 textAreaでcomposition-based languageを送信する場合、最後の単語が重複して送信される問題が存在します。
2. 原因の特定
原因は`interfaceの継承`にありました。 コンポーネントを再び抽象化する過程では、意図的に機能を制限しない限り、既存のinterfaceを適切に継承することが重要です。
以前のコード
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
// ⛳️ TextAreaをそのままspreadするのではなく、直接抽象化して継承
interface ChatInputProps {
className?: string;
value?: string;
onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
placeholder?: string;
}
const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(
({ className, value, onKeyDown, onChange, placeholder, ...props }, ref) => (
<Textarea
autoComplete="off"
value={value}
ref={ref}
onKeyDown={onKeyDown}
onChange={onChange}
name="message"
placeholder={placeholder}
className={cn(
"max-h-12 px-4 py-3 bg-background text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 w-full rounded-md flex items-center h-16 resize-none",
className,
)}
{...props}
/>
),
);
ChatInput.displayName = "ChatInput";
export { ChatInput };
このモジュールは既存のモジュールを抽象化したコンポーネントなので、shadcnのTextareaコンポーネント依存性によってこの抽象化が発生したのかどうか、履歴を確認する必要があります。
Textarea(shadcn)
import * as React from "react"
import { cn } from "@/lib/utils"
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)
}
)
Textarea.displayName = "Textarea"
export { Textarea }
そのようなことはありませんでした。単なるミスであることが確認できましたので、継承するinterfaceを修正しましょう。 選択肢は2つあります。
HTMLTextAreaElementを継承する
依存モジュールを使うので、shadcnが使用しているTextareaをそのまま継承する。
もちろん、2つ目のほうが望ましいですが、既存のモジュールで抽象化された方法を確認したところ、shadcnが提供しているinterfaceではなく、すべて直接抽象化して継承する方法を採用していました。 この場合、shadcnが提供するinterfaceがHTML APIではなく独自の宣言方式に変更された場合、このモジュールも再作業が必要になるという問題がありますが、HeadlessUI(shadcn)の性質上、HTML APIを超える可能性は低いと判断し、従来のコンベンションに従い(HTMLTextAreaElementを継承)作業することにしました。
3. 解決
interfaceを正しく継承し、不要なパラメーターを削除する簡単な作業後、PRを提出しました。
4. PRおよびマージ
メンテナーは1人で、contributionに関するドキュメントがTODOに含まれていた初期プロジェクトだったため、LinkedInプロフィールを通じてgentle pingを送りました。
マージ後、丁寧なDMまでいただきました。 メンテナーのgentleさがオープンソースに与える影響の大きさを感じました。 しばらく停滞していたオープンソース活動を再び始めてみようと思います。