generated at
render hooks pattern




>Custom Hook から Component を返却する render hooks パターンの場合、返却された Component がアンマウントされてしまうことによりバグが発生する恐れがあるので注意が必要です。
> Custom Hook から Component を返さずに React element を返す実装にすれば、 アンマウントを回避できます。
>
componentは含めないのか
useEventがあるとましになりそうな気もする



ロジックとcomponentが明らかに凝集している、という場合に有用


Modal というComponentを返している
ts
const App = () => { const [Modal, open, close, isOpen] = useModal('root', { preventScroll: true, closeOnOverlayClick: false }); return ( <div> <p>Modal is Open? {isOpen ? 'Yes' : 'No'}</p> <button onClick={open}>OPEN</button> <Modal> <div> <h1>Title</h1> <p>This is a customizable modal.</p> <button onClick={close}>CLOSE</button> </div> </Modal> </div> ); };
実装箇所
useCallback使ってる



うまく動かない例
ts
const useForm = () => { const [value, setValue] = useState(''); const Field: React.FC = useCallback( () => <input value={value} onChange={e => setValue(e.target.value)} />, [value], ); return { Field, }; };
値が入力されるたびに Field が新しく作られるので、1文字入力するたびにフォーカスが外れてしまう
どうしてもこういうAPIを提供したいならuseRef使ってハックっぽくするとか
ts
const useForm = () => { const valueRef = useRef(''); const Field: React.FC = () => { const inputRef = useRef<HTMLInputElement | null>(null); useEffect(() => { if (inputRef.current) { inputRef.current.value = valueRef.current; } }, []); const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { valueRef.current = e.target.value; }; return <input ref={inputRef} onChange={onChange} />; }; return { Field, }; };
ちなみにこうかくとめちゃくちゃバグる
ts
const useForm = () => { const [value, setValue] = useState(''); const ref = useRef(value); useEffect(() => { ref.current = value; }, [value]); const Field: React.FC = useCallback( () => ( <input value={ref.current} onChange={(e) => setValue(e.target.value)} /> ), [] ); return { Field, }; };