【第3回】Reactについて全くの無知の私が入門~実践的に使えるようになるまで (カスタマイズ編)

更新日時:2022.02.17

カテゴリ:HTML&CSS, JavaScript&jQuery, React

今回は前回作ったReactのtodo機能をカスタマイズしてみようと思います。

やりたい事

  • スタイルを当てて見た目を良くしたい
  • 文字を入力していない状態で登録を押した場合、登録しない
  • 一斉削除ボタンを設置
  • 登録した時にinputtextの中を空にする
  • input.valueが空で登録した時は処理しない

今回はこの3つのカスタマイズをしてみます!

 

CSSでスタイルを当てる

cssを使いスタイルを当てます。

index.jsを見てみると

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'; //ここでcss読み込んでる!
import Todo from './todo';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
  ,
  document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals

index.cssというファイルを読み込んでいたので試しにsrc/index.cssに記述してみます。

button{
  background-color: blue;
  color: #fff;
}

できた!

無事スタイルが当たることが確認できたのでちゃんとスタイルを当ててあげます!

スタイルを当てるためにクラスを付ける

JSXではクラスを付ける際に注意することがあるみたいです。

classではなくclassNameと記述してあげるようです。

なのでこんな感じでclassNameを付けてあげます。

<div className='todo_wrap'>

スタイルを当てる

.todo_wrap{
    background-color: #f9f9f9;
    width: 800px;
    margin: 50px auto 0;
    padding: 30px;
    input{
        width: 100%;
        padding: 10px 15px;
        font-size: 16px;
        border-radius: 10px;
        border: 1px solid #d3d3d3;
        box-sizing: border-box;
    }
    button{
        background-color: #c93a40;
        color: #fff;
        border: 1px solid #d3d3d3;
        border-radius: 20px;
        padding: 5px 20px;
        margin-left: 10px;
        cursor: pointer;
    }
    > button{
        background-color: #0074bf;
        display: block;
        margin: 10px auto 0;
    }
    ul{
        li{
            display: flex;
            justify-content: space-between;
            margin-top: 10px;
            list-style-type: none;
            border-bottom: 1px solid #000;
        }
    }
}

するとこんな感じになりました!

 

文字を入力していない状態で登録を押した場合、登録しない

次に文字を入力していない状態で登録ボタンを押した場合は登録しないように処理を追加します。

現時点で文字を入力していない状態で登録ボタンを押すとこうなります。↓

空文字でも登録されてしまう…

ということでプログラムを編集

addTodo = () => {
  const { todos, name } = this.state;
  if(name != ""){ //追加
    this.setState({
      todos: [...todos, name]
    });
  } //追加
}

nameに値が入ってくるみたいなので、入っていない場合はsetStateできないようにしました。

このsetStateのtodosに配列で一時的に保存してるのかな?

 

一斉削除ボタンを設置

削除メソッドを見てみる。

ここでもsetStateしている…

登録の時も削除の時もsetState使ってる!

todos: [...todos.slice(0, index), ...todos.slice(index + 1)]

このindexってのはtodosの配列のindex番号がkeyになっていて使われているみたい。

だから5つあるうちの3つ目の項目を削除したいときに選択した行のkeyがindexになる。

3つ目を削除する場合、todos.slice(0, index)だったらtodos.slice(0, 2)ってなるから仮に以下の配列の場合に
sliceしたら「あ,い」しか残らない。

todos: Array(5)
0: "あ"
1: "い"
2: "う"
3: "え"
4: "お"

第二引数は「え,お」しか残らない。

残ったやつを再セットするから

todos: Array(5)
0: "あ"
1: "い"
2: "え"
3: "お"

結果こうなるということか。納得!

一斉にすべてを削除したい場合は下記のように空っぽにしてあげればよくない?

// 一斉削除
removeallTodo = () => {
    const { todos, name } = this.state;
    this.setState({
        todos: []
    });
}

renderの中にもボタンを作る

<button onClick={this.removeallTodo} >一斉削除</button>

適当にたくさん追加して、一斉削除ボタンをクリック。。。。

できた!!!╰(*°▽°*)╯

思ったより簡単に実装できましたな!

ついでにcssで一斉削除ボタンも赤くしておこう。

button{
    background-color: #c93a40;
    color: #fff;
    border: 1px solid #d3d3d3;
    border-radius: 20px;
    padding: 5px 20px;
    margin-left: 10px;
    cursor: pointer;
}
> button{
    display: block;
    margin: 10px auto 0;
}
.b_button{
    background-color: #0074bf;
}
.r_button{
    background-color: #c93a40;
}

 

登録した時にinputtextの中を空にする

これは簡単ですね!

// 行を追加する
addTodo = () => {
    const { todos, name } = this.state;
    document.querySelector('input').value = ""
    if(name != ""){
        this.setState({
            todos: [...todos, name]
        });
    }
}

 

input.valueが空で登録した時は処理しない

これも簡単!

// 行を追加する
addTodo = () => {
    if(document.querySelector('input').value != ""){
        document.querySelector('input').value = ""
        const { todos, name } = this.state;
        if(name != ""){
            this.setState({
                todos: [...todos, name]
            });
        }
    }
}

こんな感じで一時的なTodoアプリは完成です!( •̀ ω •́ )✧

 

ソースコードまとめ

todo.js

import React, { Component } from 'react';


// todoクラス
export default class Todo extends Component {


    constructor(props) {
        super(props);
        this.state = {
            todos: [],
            name: ''
        };
    }


    onInput = (e) => {
        this.setState({
            name: e.target.value
        });
    }


    // 行を追加する
    addTodo = () => {
        if(document.querySelector('input').value != ""){
            document.querySelector('input').value = ""
            const { todos, name } = this.state;
            if(name != ""){
                this.setState({
                    todos: [...todos, name]
                });
            }
        }
    }


    // 行を削除する
    removeTodo = (index) => {
        const { todos, name } = this.state;
        this.setState({
            todos: [...todos.slice(0, index), ...todos.slice(index + 1)]
        });
    }


    // 一斉削除
    removeallTodo = () => {
        const { todos, name } = this.state;
        this.setState({
            todos: []
        });
    }


    // ベースとなるHTMLを描画するメソッド
    render() {
        const { todos } = this.state;
        return (
            <div className='todo_wrap'>
                <input type="text" onInput={this.onInput} />
                <button className='b_button' onClick={this.addTodo} >登録</button>
                <button className='r_button' onClick={this.removeallTodo} >一斉削除</button>
                <ul>
                    {todos.map(
                        (todo, index) => <li key={index}>
                        {todo}
                        <button className='r_button' onClick={() => { this.removeTodo(index) }}>削除</button>
                        </li>
                    )}
                </ul>
            </div>
        );
    }
}

 

index.scss

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen','Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}


code {
    font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',monospace;
}


.todo_wrap{
    background-color: #f9f9f9;
    width: 800px;
    margin: 50px auto 0;
    padding: 30px;
    input{
        width: 100%;
        padding: 10px 15px;
        font-size: 16px;
        border-radius: 10px;
        border: 1px solid #d3d3d3;
        box-sizing: border-box;
    }
    button{
        background-color: #c93a40;
        color: #fff;
        border: 1px solid #d3d3d3;
        border-radius: 20px;
        padding: 5px 20px;
        margin-left: 10px;
        cursor: pointer;
    }
    > button{
        display: block;
        margin: 10px auto 0;
    }
    .b_button{
        background-color: #0074bf;
    }
    .r_button{
        background-color: #c93a40;
    }
    ul{
        li{
            display: flex;
            justify-content: space-between;
            margin-top: 10px;
            list-style-type: none;
            border-bottom: 1px solid #000;
        }
    }
}

 

次回はReactで実際にサイトを作ってみます!!

Leave a Comment

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。

CAPTCHA