【初心者向け】Reactでテキスト入力時の入力チェックを実装してみた

スポンサーリンク
JavaScript

前回の記事で作成したReactメモアプリに、入力チェックを実装してみました。

前回の記事

参考にした書籍

モダンJavaScriptの基本から始める React実践の教科書 (最新ReactHooks対応) | じゃけぇ(岡田 拓巳) | コンピュータ・IT | Kindleストア | Amazon
Amazonでじゃけぇ(岡田 拓巳)のモダンJavaScriptの基本から始める React実践の教科書 (最新ReactHooks対応)。アマゾンならポイント還元本が多数。一度購入いただいた電子書籍は、KindleおよびFire端末、スマートフォンやタブレットなど、様々な端末でもお楽しみいただけます。

元のコード

import '../App.css';
import {useState,FC, ChangeEvent} from 'react';
import styled from 'styled-components';
import {MemoList} from './MemoList';
import {useMemoList} from '../hooks/useMemoList';
import { useCallback } from 'react';

export const App:FC = () => {

const {memos,addTodo,deleteTodo} = useMemoList();
const [text,setText] =useState<string>('');

const onChangeText = (e:ChangeEvent<HTMLInputElement>) => 
  setText(e.target.value);

const onClickAdd = () => {
  addTodo(text);
  setText('');
};

const onClickDelete = useCallback((index:number) => {
  deleteTodo(index);
},[deleteTodo]);


  return (<div>
    <h1>メモアプリ</h1>
    <input type='text' value={text} onChange={onChangeText} placeholder='メモを入力'/>
    <SButton onClick={onClickAdd}>追加</SButton>
    <p>メモ一覧</p>
    <MemoList memos={memos} onClickDelete={onClickDelete}></MemoList>
    </div>
  );
};

const SButton = styled.button`
  margin-left:16px;
`;
import {FC} from 'react';
import styled from 'styled-components';


type Props = {
    memos:string[];
    onClickDelete:(index:number) => void;
}

export const MemoList:FC<Props> = props => {
    const {memos,onClickDelete} = props;

    return (
    <SContainer>
      <ul>
        {memos.map((memo,index)=>(
          <li key={memo}>
            <SMemoWrapper>
              <p>{memo}</p>
            </SMemoWrapper>
            <SButton onClick={() => onClickDelete(index)}>削除</SButton>
          </li>
        ))}
      </ul>
    </SContainer>
    );
} ;

const SButton = styled.button`
  margin-left:16px;
`;

const SContainer = styled.div`
  padding: 0.5em 1em;
  margin: 2em 0;
  color: #5d627b;
  background: white;
  border-top: solid 5px #5d627b;
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.22);
`;

const SMemoWrapper = styled.div`
  display:flex;
  align-items:center;
`;
import { useCallback,useState } from "react";


export const useMemoList = () => {
    const [memos,setMemos] = useState<string[]>([]);

    const addTodo = useCallback((text:string) => {
        const newMemos = [...memos];
        newMemos.push(text);
        setMemos(newMemos);
    },[memos]);

    const deleteTodo =useCallback((index:number) => {
        const newMemos = [...memos];
        newMemos.splice(index,1);
        setMemos(newMemos);
    },[memos]);

    return {memos,addTodo,deleteTodo}
};

課題

現状だと以下のように、空欄の状態でもメモとして一覧に追加されてしまうので、これをどうにかしたい。

改修方針

以下の改修方針で修正することにしました。

  • そもそも、テキスト未入力の状態で追加ボタン押下ができないようにする
  • そのため、初期表示時&テキスト未入力時はボタンが非活性の状態にする
  • テキスト未入力時は入力されていない旨のメッセージを表示するようにする
  • テキスト入力された状態だと、ボタンが活性化するようにする

完成品

完成品は以下です。今のところどうやっても空欄でメモ追加ができなくなりました。

改修後コード

改修後コードは以下です。
App.tsxのみ修正しました。

import '../App.css';
import {useState,FC, ChangeEvent} from 'react';
import styled from 'styled-components';
import {MemoList} from './MemoList';
import {useMemoList} from '../hooks/useMemoList';
import { useCallback } from 'react';


export const App:FC = () => {

const {memos,addTodo,deleteTodo} = useMemoList();
const [text,setText] =useState<string>('');
const [nameError, setNameError] = useState<string>('')
const [buttonDisabled, setEbuttonDisabled] = useState<boolean>(false)

const onChangeText = (e:ChangeEvent<HTMLInputElement>) => {
  let value = e.target.value;
  setText(value)};


const handleBlur = (e:any) => {
    const name = e.target.value
    if (!name) {
      setNameError('メモが入力されていません')
      setEbuttonDisabled(false)
    } else {
      setNameError('')
      setEbuttonDisabled(true)
    }
}

const onClickAdd = () => {
  addTodo(text);
  setText('');
  setEbuttonDisabled(false)
};

const onClickDelete = useCallback((index:number) => {
  deleteTodo(index);
},[deleteTodo]);

  return (<div>
    <h1>メモアプリ</h1>
    {nameError && <SError>{nameError}</SError>}
    <input type='text' value={text} name='text' onChange={onChangeText} placeholder='メモを入力' onBlur={handleBlur}/>
    <SButton disabled={!buttonDisabled} onClick={onClickAdd}>追加</SButton>
    <p>メモ一覧</p>
    <MemoList memos={memos} onClickDelete={onClickDelete}></MemoList>
    </div>
  );
};

const SButton = styled.button`
  margin-left:16px;
`;

const SError = styled.p`
  color:red;
  font-size:10px
`;

少し解説

①エラーメッセージ、ボタン活性の状態をもつStateを作成する
ボタン活性の状態は初期表示時も非活性にしたいため、デフォルトでfalseを入れておく

const [nameError, setNameError] = useState(”)
const [buttonDisabled, setEbuttonDisabled] = useState(false)

②ボタンはbuttonDisabledの値でdisabledを判定するようにする

<SButton disabled={!buttonDisabled} onClick={onClickAdd}>追加</SButton>

③テキスト入力時にはhandleBlur関数の実行で入力値が存在しない場合はエラーメッセージをセット&ボタン非活性の状態をセットする

const handleBlur = (e:any) => {
const name = e.target.value
if (!name) {
setNameError(‘メモが入力されていません’)
setEbuttonDisabled(false)
} else {
setNameError(”)
setEbuttonDisabled(true)
}}

④追加ボタン押下時のonClickAddの処理実行後には、テキストはクリアされる仕様のため、それに合わせてボタンも非活性にするようにsetEbuttonDisabled(false)を追加する

const onClickAdd = () => {
addTodo(text);
setText(”);
setEbuttonDisabled(false)
};

参考にしたサイト

これを実装するために「React バリデーションチェック」でかなり調べてみて、React Hook Form 等色々出てきたのですが最終的には以下のサイトの内容を参考にさせてもらいました。わかりやすいしとても簡単でした。

React hookで気持ちよく入力チェック〜エラー判定を行う
https://qiita.com/Coolucky/items/1721c0f071601eb69831

読んでいただきありがとうございました!

コメント

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