まずはInput
を使って、InputForm
を作ります。
InputForm
にInput
と一つのOKボタンが含まれています。
Input
の値がtmpInputValue
に保存されてます。
OKボタンを押すと、value
の値がtmpInputValue
に更新されます。
OKボタンを押さなくて、別の所をクリックすると、value
の値が更新されません。
const OKButton = () => (
<button
className="m-2"
type="submit"
onMouseDown={(e) => {
setValue(inputTmpValue);
}}
>
✅
</button>
);
const InputForm = ({ isInput, text }: { isInput: boolean; text: string; }) => {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (isInput && inputRef.current) {
inputRef.current.focus();
}
}, [isInput]);
return (
<form
style={{ display: isInput ? "block" : "none" }}
className="border-collapse"
action={() => { console.log("action"); }}
onBlur={(e) => {
setIsInput(!isInput);
setInputTmpValue(value);
}}
>
<input
className="border-2"
type="text"
name="input"
value={inputTmpValue}
onChange={(e) => {
setInputTmpValue(e.target.value);
}}
ref={inputRef}
/>
<OKButton />
</form>
);
};
次に、Value
を表示するのSpan
を作ります。
Span
をクリックすると、Span
が消えて、InputForm
が現れます。
その状態はisInput
に保存します。
const Span = ({ isInput, text }: { isInput: boolean, text: string; }) => (
<span
style={{ display: !isInput ? "block" : "none" }}
className=" border-red-300 border-2 min-h-4"
onClick={() => setIsInput(!isInput)}
>
{text}
</span>
);
最後に、これらをまとめます。
export default function Block() {
const [value, setValue] = useState("");
const [inputTmpValue, setInputTmpValue] = useState(value);
const [isInput, setIsInput] = useState(false);
const OKButton = () => (
...
);
const Span = ({ isInput, text }: { isInput: boolean, text: string; }) => (
...
);
const InputForm = ({ isInput, text }: { isInput: boolean; text: string; }) => {
...
};
return (
<div>
<Span isInput={isInput} text={value} />
<InputForm isInput={isInput} text={value} />
</div>
);
}
出来上がりです!