6
3

More than 3 years have passed since last update.

React 初心者向け「簡単Blog」- Blog一覧・検索編

Last updated at Posted at 2019-10-08

簡単Blog

Blogのリスト・検索:登録・編集・削除までを行う機能を実装します。
今日はBlogの親コンポーネントとBlogの内容を表示する子コンポーネントを作って検索までやってみます。
Blogはユーザー名、タイトル、Blog内容で構成されています。

スクリーンショット 2019-10-09 0.06.29.png

コンポーネント構成

Untitled Diagram-7.png

react-bootstrap設置

react-bootstrapを少し使ってみました。
npmで設置してImportするだけで簡単に使えました。
Bootstrapの説明は省略します。興味ある方は以下のリンク参照してください。
https://react-bootstrap.netlify.com/getting-started/introduction/

npm install react-bootstrap bootstrap

Blogの親コンポーネント実装

stateで状態を管理
子コンポーネントにPropsを利用して状態を渡す。

constructorにstate定義

keyword:検索文字列
blogData: 複数のBlogを表示するように配列にする

constructor(props) {
      super(props)
    this.state = {
        keyword: "",
        blogData: [
          {
            user_name: "吉田",
            title: "おはよう",
            content: "朝はおはよう〜"
          },
          ...
        ]
      }

eventハンドラー追加(検索文字が入力される時にkeyword状態を変更する事でViewが更新される)

  constructor(props) {
      ...
      this.onChange = this.onChange.bind(this);
  }
    onChange(e) {
        this.setState({
            keyword: e.target.value
        })
    }

render()実装

複数のコンポーネントデータからKeyword状態でFilterしたBlogInfoデータのコンポーネントを生成。
SearchテキストのValueにthis.state.keywordを設定しているのでonChangeのe.target.valueで検索文字列が変わるたびにStateに変更を持たせて、Renderingさせる。

    render() {
        const getComponents = (data) => {
            data = data.filter(
                (blog) => {
                    return blog.title.toLowerCase().indexOf(this.state.keyword.toLowerCase()) > -1;
                });
            data.sort();
            return  data.map((blog) => {
                return (
                <div>
                <BlogInfo blog={blog}></BlogInfo>
                </div>
                )
            })
        }
        return (
            <div>
            <h1>Blog</h1>
            <FormControl type="text" placeholder="Search" className="mr-sm-2" value={this.state.keyword} onChange={this.onChange}/>
            <div>{getComponents(this.state.blogData)}</div>
            </div>
        )
    }

Blog.js(親コンポーネントコード)

Blog.js
import React, { Component } from 'react'
import BlogInfo from './BlogInfo'
import {FormControl} from 'react-bootstrap'

export default class Blog extends Component {
    constructor(props) {
      super(props)
      this.state = {
        keyword: "",
        blogData: [
          {
            user_name: "吉田",
            title: "おはよう",
            content: "朝はおはよう〜"
          },
          {
            user_name: "高橋",
            title: "こんにちは",
            content: "昼はこんにちは〜"
          },
          {
            user_name: "木村",
            title: "こんばんは",
            content: "夜はこんばんは〜"
          }
        ]
      }
      this.onChange = this.onChange.bind(this);
    }


    onChange(e) {
        this.setState({
            keyword: e.target.value
        })
    }

    render() {
        const getComponents = (data) => {
            data = data.filter(
                (blog) => {
                    return blog.title.toLowerCase().indexOf(this.state.keyword.toLowerCase()) > -1;
                });
            data.sort();
            return  data.map((blog) => {
                return (
                <div>
                <BlogInfo blog={blog}></BlogInfo>
                </div>
                )
            })
        }
        return (
            <div>
            <h1>Blog</h1>
            <FormControl type="text" placeholder="Search" className="mr-sm-2" value={this.state.keyword} onChange={this.onChange}/>
            <div>{getComponents(this.state.blogData)}</div>
            </div>
        )
    }
}

BlogInfo(子コンポーネント実装)

親コンポーネントで以下の様にblogと言う名前のPropsにBlog状態を渡している。
<BlogInfo blog={blog}></BlogInfo>
子コンポーネントからは{this.props.blog.user_name}でそのBlog状態を受け取ることができる。
その情報を子コンポーネントはRenderingする。
CardはBootStrapのコンポーネント。

BlogInfo.js
import React, { Component } from 'react'
import {Card} from 'react-bootstrap'

export default class  BlogInfo  extends Component{
  render() {
    return(
        <Card border="info" style={{ width: '18rem' }}>
            <Card.Header>{this.props.blog.user_name}</Card.Header>
            <Card.Body>
            <Card.Title>{this.props.blog.title}</Card.Title>
            <Card.Text>
             内容: {this.props.blog.content}
            </Card.Text>
            </Card.Body>
        </Card>
    )
  }
}

App.js

App.js
import React, { Component } from 'react'
import './App.css';
import Blog from './components/Blog';

class App extends Component {
  render() {
    return (
      <Blog></Blog>
    );
  }
}

export default App

完成

Blog.gif

6
3
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
6
3