LoginSignup
64
50

More than 3 years have passed since last update.

『React』 +『Redux』 + 『Firebase』でLINE風のChat機能を作ろう! 【Component編】

Last updated at Posted at 2019-05-31

はじめに

前回の記事では

  • create-react-app
  • パッケージのインストール
  • Firebaseとの紐付けを行いました。

今回は、Material-UIを用いてComponentを作成していきましょう!

前回の記事
『React』 +『Redux』 + 『Firebase』でLINE風のChat機能を作ろう! 【準備編】

実装してみよう!

1. 使いたいComponentをMaterial-UIから探す

https://material-ui.com/にアクセスし、自分の好みのデザインのコンポーネントを探しましょう!

ヘッダー

スクリーンショット 2019-05-31 10.58.41.png

メッセージ入力欄

スクリーンショット 2019-05-31 11.05.03.png

メッセージ送信ボタン

スクリーンショット 2019-05-31 10.57.09.png

メッセージ表示欄

スクリーンショット 2019-05-31 11.06.48.png

今回は以上の4つのコンポーネントを用いてアプリを作成しました。

2. Material-UIのComponentを自分なりにアレンジする

使いたいComponentが決まったら、それをベースにして自分なりに少しアレンジを加えてみましょう!

ページ全体

src/App.js
import React, {Component} from 'react';

import {connect} from 'react-redux';

import AlignItemsList from './components/AlignItemsList';
import ButtonAppBar from './components/ButtonAppBar.js';
import TextInput from './components/TextInput.js';

import {firebaseDb} from './firebase';

import './styles/App.css';

const messagesRef = firebaseDb.ref('messages');

class App extends Component {
  render() {
    return (
      <React.Fragment>
        <ButtonAppBar />
        <div className="App">
          <AlignItemsList />
          <TextInput value="メッセージを入力" />
        </div>
      </React.Fragment>
    );
  }
}

export default App;
src/styles/App.css
.App{
  margin: 0 auto;
  max-width: 500px;
}

@media screen and (max-width:520px) { 
  /* 画面サイズが520pxからはここを読み込む */
  .App{
    margin: 0 20px;
  }
}

.App ul {
  margin: 10px auto;
}

.App ul li {
  padding-left: 0;
  display: flex;
  align-items: center;
}

.App ul .MuiDivider-inset{
  margin-left: 57px;
}

.App ul li .MuiListItemAvatar-alignItemsFlexStart {
  margin-top: 0;
}

ヘッダー

src/components/ButtonAppBar.js
import React from 'react';
import {makeStyles} from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import '../styles/ButtonAppBar.css';

const useStyles = makeStyles(theme => ({
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginRight: theme.spacing(2),
  },
  title: {
    flexGrow: 1,
  },
}));

function ButtonAppBar() {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <AppBar position="static">
        <Toolbar>
          <IconButton
            edge="start"
            className={classes.menuButton}
            color="inherit"
            aria-label="Menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h4" className={classes.title}>
            PigTalk
          </Typography>
          <Button color="inherit">Login</Button>
        </Toolbar>
      </AppBar>
    </div>
  );
}

export default ButtonAppBar;
src/styles/ButtonAppBar.css
h4 {
    text-align: center;
}

メッセージ入力欄

src/components/TextInput.js
import React, {Component} from 'react';

import TextField from '@material-ui/core/TextField';
import '../styles/TextInput.css';
import SendButtons from './SendButton';

import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';

class TextInput extends Component {
  render() {
    return (
      <React.Fragment>
        <form className="wrap" noValidate autoComplete="off">
          <TextField
            id="standard-text"
            label="メッセージを入力"
            className="text"
            margin="normal"
          />
          <SendButtons />
        </form>
      </React.Fragment>
    );
  }
}

export default TextInput;
src/styles/TextInput.css
.wrap {
    display: flex;
    justify-content: center;
}

.wrap .text {
    width: 80%;
}

.wrap button {
    margin-top: 24px;
    margin-right: 0;
    width: 20%;
}

メッセージ送信ボタン

src/components/SendButton.js
import React from 'react';

import Button from '@material-ui/core/Button';
import {makeStyles} from '@material-ui/core/styles';
import Icon from '@material-ui/core/Icon';

const useStyles = makeStyles(theme => ({
  button: {
    margin: theme.spacing(1),
  },
  leftIcon: {
    marginRight: theme.spacing(1),
  },
  iconSmall: {
    fontSize: 20,
  },
}));

function SendButtons() {
  const classes = useStyles();

  return (
    <Button variant="contained" color="primary" className={classes.button}>
      <Icon>send</Icon>
    </Button>
  );
}

export default SendButtons;

メッセージ表示欄

src/components/AlignItemsList.js
import React from 'react';
import {makeStyles} from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import Divider from '@material-ui/core/Divider';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import Avatar from '@material-ui/core/Avatar';

const useStyles = makeStyles(theme => ({
  root: {
    backgroundColor: theme.palette.background.paper,
  },
  inline: {
    display: 'inline',
  },
}));

function AlignItemsList() {
  const classes = useStyles();

  return (
    <List className={classes.root}>
      <ListItem alignItems="flex-start">
        <ListItemAvatar>
          <Avatar
            alt="Remy Sharp"
            src="https://hellogiggles.com/wp-content/uploads/2015/03/11/micro-pig-LondonPignic.jpg"
          />
        </ListItemAvatar>
        <ListItemText primary="Hello World" />
      </ListItem>
      <Divider variant="inset" component="li" />
    </List>
  );
}

export default AlignItemsList;

送信ボタンのIconを使うために

public/index.html
<head>
    ...
    <!-- Google Icon -->
    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
    />
    ...
</head>

実装完了

スクリーンショット 2019-05-31 11.43.36.png

次回は

  • 『Redux』を用いてactionreducerstoreを定義し、状態管理を実装
  • 『Firebase』『Realtime Database』とのデータの受け渡しの実装

をします!

リファレンス

64
50
4

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
64
50