「モダンJavaScriptの基本から始めるReact実践の教科書」の感想・備忘録8

「モダンJavaScriptの基本から始めるReact実践の教科書」の感想・備忘録7の続き

メモアプリの作成

カスタムフック化前

  1. npx create-react-app memo-app –template typescript
  2. cd memo-app
  3. mv src/App.tsx src/components/App.tsx
  4. mkdir src/{components,hooks,types}
  5. touch src/components/MemoList.tsx
  6. touch src/types/MemoListProps.ts
import {ChangeEvent, useState, useCallback, FC} from 'react';
import {MemoList} from './MemoList';

const App: FC = () => {
  const [text, setText] = useState<string>('')
  const [memos, setMemos] = useState<string[]>([])
  const onChangeText = (e:ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value)
  }
  const onClickAdd = () => {
    setMemos([...memos, text])
    setText('')
  }
  const onClickDelete = useCallback((index: number) => {
    const newMemos = [...memos]
    newMemos.splice(index, 1)
    setMemos(newMemos)
  }, [memos])
  return (
    <>
    <input type="text" value={text} onChange={onChangeText}/>
    <button onClick={onClickAdd}>追加</button>
    <MemoList memos={memos} onClickDelete={onClickDelete}/>
    </>
  );
}
export default App
import {FC} from 'react';
import type { MemoListProps } from '../types/MemoListProps'

export const MemoList: FC<MemoListProps> = props => {
  const {memos, onClickDelete} = props
  return (
    <ul>
      {memos.map((memo, index) => (
        <li key={memo}>{memo}<button onClick={() => onClickDelete(index)}>削除</button></li>
      ))}
    </ul>
  );
}
export type MemoListProps = {
  memos: string[],
  onClickDelete: (index: number) => void
}

カスタムフック化

touch src/hooks/useMemoList.ts

import {useCallback, useState} from 'react';

export const useMemoList = () => {
  const [memos, setMemos] = useState<string[]>([])
  
  const addMemo = useCallback((text: string) => {
    setMemos([...memos, text])
  }, [memos])

  const deleteMemo = useCallback((index: number) => {
    const newMemos = [...memos]
    newMemos.splice(index, 1)
    setMemos(newMemos)
  }, [memos])
  
  return {memos, addMemo, deleteMemo};
}
import {ChangeEvent, useState, useCallback, FC} from 'react';
import {MemoList} from './MemoList';
import {useMemoList} from '../hooks/useMemoList';

const App: FC = () => {
  const {memos, addMemo, deleteMemo} = useMemoList()
  const [text, setText] = useState<string>('')
  const onChangeText = (e:ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value)
  }
  const onClickAdd = () => {
    addMemo(text)
    setText('')
  }
  const onClickDelete = useCallback((index: number) => {
    deleteMemo(index)
  }, [deleteMemo]) // deleteMemoはメモ化されているため依存配列に指定する必要がある
  return (
    <>
    <input type="text" value={text} onChange={onChangeText}/>
    <button onClick={onClickAdd}>追加</button>
    <MemoList memos={memos} onClickDelete={onClickDelete}/>
    </>
  );
}
export default App

コメント

タイトルとURLをコピーしました