2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React練習) テキストエリアに文字を入力しボタンをおすとその内容が表示される。というシンプルなアプリ

Last updated at Posted at 2020-01-11

つくったもの

テキストエリアに文字を入力しボタンをおすと、
その内容が表示される。というシンプルな機能です。

ファイル構造

project/
 ├ node_modules/
 ├ src/
 |  ├ App.css 
 |  ├ App.js 
 |  ├ index.css  
 |  ├ index.js 
 |  ├ serviceWorkers.js   
 │ └ components/
 │   ├ Comment/
 |   |   └ Comment.jsx
 │   ├ CommentAdder/
 |   |    └ CommentAdder.jsx
 │   └ CommentsList/
 |       └ CommentsList.jsx
 ├ .gitignore
 ├ README.md
 ├ yarn.lock
 └ package.json 

手順

1 create-react-appを導入。App.jsを作成
yarn global add create-react-app
create-react-app <project>

で作れます。
詳しくはこちら

もとから入っているApp.jsの中身を以下のように変更します。

App.jsはこのアプリの機能全体を包む箱となります。

import React from "react";
import "./App.css";
import CommentsList from "./components/CommentsList/CommentsList";
import CommentAdder from "./components/CommentAdder/CommentAdder";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { list: [] };
  }

  addComment = newComment => {
    this.setState({ list: [...this.state.list,newComment] });
  };

  render() {
    return (
      <div className="App">
        <CommentAdder onAddComment={this.addComment} />
        <CommentsList list={this.state.list} />
      </div>
    );
  }
}

export default App;
2 CommentsList.jsxを作成

CommentsList.jsxは、コメントが表示される箱となります。

props とはpropertiesの省略形で、親コンポーネントから渡されてくるオブジェクトのことです。親であるApp.jsで以下のラインがpropsを設定している箇所になります。

<CommentsList list={this.state.list} />

App.jsのthis.stateをみてください。そこにある配列を渡しています。
配列なのでArrayメソッドが使えます。

配列の要素が実際に画面に出現するコメントになります。

コメントを表示させる機能は別ファイルComment.jsxとして作成し、
App.jsからみて孫コンポーネント、CommentsList.jsxからみて子コンポーネントとしてネストします。

表示させたいのはmapメソッドでループされている全ての要素一つ一つなので、
propsの設定の仕方は以下のようになります。
const comments = props.list.map(comment => <Comment comment={comment} />);

import React from "react";
import Comment from "../Comment/Comment";

const CommentsList = props => {
  const comments = props.list.map(comment => <Comment comment={comment} />);
  return (
    <div className="commentsArea">
      <ul>{comments}</ul>
    </div>
  );
};

export default CommentsList;
3 Comment.jsxを作成

Comment.jsxは、一つずつのコメントそのものとなります。
これはCommentsList.jsx から渡されてきたpropsに入っているcommentをただpタグで表示するだけ、という機能になります。

import React from "react";

const Comment = props =>{
    return (
      <div>
        <p>{props.comment}</p>
      </div>
    );
} 
  
export default Comment;
4 CommentAdder.jsxを作成

textareaに変更が生じたら、CommentAdderのステートに格納する。
ボタンが押されたら、その格納されているステートを、親コンポーネントであるApp.jsに渡す。
ということをしています。

ここで問題なのが、Reactではデータはpropsを用いてデータを親から子方向に渡していきますが、逆方向、子から親方向へはpropsをつかって渡すことができません。

そのときは、親コンポーネントからpropsとしてコールバックを子にわたし、
それを子コンポーネントの中で実行することで実現します。

わかりにくいのでコードをみてみましょう。

import React from "react";

class CommentAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = { addedComment: "" };
  }

  onChange = event => {
    this.setState({ addedComment: event.target.value });
  };

  render() {
    return (
      <div className="adderContainer">
        <textarea
          className="textArea"
          cols="30"
          rows="3"
          value={this.state.addedComment}
          onChange={this.onChange}
        ></textarea>
        
        <button
          className="button"
          onClick={() => {
            this.props.onAddComment(this.state.addedComment); //ここで親から渡されたメソッドを実行
            this.setState({addedComment:""}) //textareaを空にする
          }}
        >
          ADD
        </button>
      </div>
    );
  }
}

export default CommentAdder;

つまづいたところ

textareaに入力した値を描画すること

onChangeメソッドを作成し、textareaに変更が生じたらその中にある値をステートに入れる、ということで解決しました。

公式ドキュメントを参考にしました。

気をつけたいこと

ステートはimmutable!

CommentAdder 内で、ステートに新しいコメントをセットするメソッドaddCommentを書いていますが、始めはこのようにpushを使っていました。

しかし、Reactではステートはimmutableです。
オリジナルの配列を変更してしまうメソッドは使用禁止です。pushは元の配列そのものに、新しい要素を追加してしまうため、つかってはいけません。

私ははじめこのように記述しており、動作はしていましたが、書き直しました。

//こちらはダメな例です
addComment = newComment => {
    this.state.list.push(newComment);
    this.setState({ list: this.state.list });
  };

その他参照ページ

Spread Syntax
Array.protptype.push()
JavaScriptでイミュータブルに配列を操作するメソッドまとめ

以上です。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?