Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

カードを作る

CodeSandBoxのテンプレートはこちら

「いいね!」の実装

2−1

onClick={() => {alert('いいね!')}}

Stateの管理

isSwipedStateの宣言

2−2

const [isSwiped, setIsSwiped] = React.useState(false);

ボタンのタップとState変化の結びつけ

2−3

onClick={() => {
  setIsSwiped(true);
}}

isSwipedStateによってCSSのクラスを付け加える

2−4

className={`card ${isSwiped ? "card-swiped" : ""}`}

カードスワイプ用のスタイル

2−5

.card-swiped {
  transform: translate(400px) rotate(50deg);
  opacity: 0;
  transition: all 1s ease-in-out;
}

cardのコンポーネント化

propsを受け取れるようにしたcard.js

3−1

import React from "react";

import "./styles.css";

export function Card(props) {
  return (
    <div
      className={`card ${props.isSwiped ? "card-swiped" : ""}`}
      style={{
        backgroundImage: `url(${props.image})`
      }}
    >
      <div className="info">
        <div className="name">
          <span>
            <svg style={{ width: "10px", height: "10px" }} viewBox="0 0 24 24">
              <path
                fill="#01cb6f"
                d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"
              />
            </svg>
          </span>
          <span>{props.name}</span>
          <span className="age">{props.age}歳</span>
          <span className="prefecture">{props.prefecture}</span>
          <span className="percent">
            <span>
              <svg
                style={{ width: "10px", height: "10px" }}
                viewBox="0 0 24 24"
              >
                <path
                  fill="#f67272"
                  d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"
                />
              </svg>
            </span>
            <span>{props.rate}%</span>
          </span>
        </div>
        <div className="communities">
          <span className="community">{props.community}</span>
        </div>
      </div>
    </div>
  );
}

index.jsでのCardコンポーネントの呼び出し

3−2

import { Card } from "./card";

3−3

<Card
  name="ゆみ"
  age="23"
  rate="95"
  community="まじめに探しています"
  image="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80"
  isSwiped={isSwiped}
/>

userListとcurrentUser,nextUserの設定

userListの初期値

4-1

[
    {
      name: "ゆみ",
      age: 23,
      rate: 95,
      community: "まじめに探しています",
      image:
        "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80"
    },
    {
      name: "OT",
      age: 24,
      rate: 90,
      community: "よく笑う人が好き",
      image:
        "https://images.unsplash.com/photo-1519742866993-66d3cfef4bbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=581&q=80"
    },
    {
      name: "OP",
      age: 25,
      rate: 40,
      community: "旅行大好き!",
      image:
        "https://images.unsplash.com/photo-1496840220025-4cbde0b9df65?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=668&q=80"
    }
  ]

currentUserの初期値

4-2

userList[0]

nextUserの初期値

4-3

userList[1]

currentUser,nextUserを参照するようにした、Cardコンポーネント達

4-4

{nextUser !== undefined ? (
          <Card
            name={nextUser.name}
            age={nextUser.age}
            rate={nextUser.rate}
            community={nextUser.community}
            image={nextUser.image}
            isSwiped={false}
          />
        ) : null}
        {currentUser !== undefined ? (
          <Card
            name={currentUser.name}
            age={currentUser.age}
            rate={currentUser.rate}
            community={currentUser.community}
            image={currentUser.image}
            isSwiped={isSwiped}
          />
        ) : null}

4−X

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";
import { Card } from "./card";

function App() {
  const [userList, setUserList] = React.useState([
    {
      name: "ゆみ",
      age: 23,
      rate: 95,
      community: "まじめに探しています",
      image:
        "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80"
    },
    {
      name: "OT",
      age: 24,
      rate: 90,
      community: "よく笑う人が好き",
      image:
        "https://images.unsplash.com/photo-1519742866993-66d3cfef4bbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=581&q=80"
    },
    {
      name: "OP",
      age: 25,
      rate: 40,
      community: "旅行大好き!",
      image:
        "https://images.unsplash.com/photo-1496840220025-4cbde0b9df65?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=668&q=80"
    }
  ]);
  const [isSwiped, setIsSwiped] = React.useState(false);
  const [currentUser, setCurrentUser] = React.useState(userList[0]);
  const [nextUser, setNextUser] = React.useState(userList[1]);
  return (
    <div className="App">
      <div className="card-container">
        <Card
          name={nextUser.name}
          age={nextUser.age}
          rate={nextUser.rate}
          community={nextUser.community}
          image={nextUser.image}
          isSwiped={false}
        />
        <Card
          name={currentUser.name}
          age={currentUser.age}
          rate={currentUser.rate}
          community={currentUser.community}
          image={currentUser.image}
          isSwiped={isSwiped}
        />
      </div>
      <div className="buttons">
        <button className="button-nope">
          <svg style={{ width: "40px", height: "40px" }} viewBox="0 0 24 24">
            <path
              fill="#cbced0"
              d="M10,9V5L3,12L10,19V14.9C15,14.9 18.5,16.5 21,20C20,15 17,10 10,9Z"
            />
          </svg>
        </button>
        <button
          className="button-like"
          onClick={() => {
            setIsSwiped(true);
          }}
        >
          <svg style={{ width: "28px", height: "28px" }} viewBox="0 0 24 24">
            <path
              fill="#f67272"
              d="M23,10C23,8.89 22.1,8 21,8H14.68L15.64,3.43C15.66,3.33 15.67,3.22 15.67,3.11C15.67,2.7 15.5,2.32 15.23,2.05L14.17,1L7.59,7.58C7.22,7.95 7,8.45 7,9V19A2,2 0 0,0 9,21H18C18.83,21 19.54,20.5 19.84,19.78L22.86,12.73C22.95,12.5 23,12.26 23,12V10M1,21H5V9H1V21Z"
            />
          </svg>
        </button>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

最終的なクリック時の処理

4-2

  const clickLike = () => {
    setIsSwiped(true);
    setTimeout(() => {
      setIsSwiped(false);
      setCurrentUser(nextUser);
      setNextUser(userList[2]);
      setUserList(userList.slice(1));
    }, 1000);
  };

ハンズオンのゴール

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";
import { Card } from "./card";

function App() {
  const [userList, setUserList] = React.useState([
    {
      name: "ゆみ",
      age: 23,
      rate: 95,
      community: "まじめに探しています",
      image:
        "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80"
    },
    {
      name: "OT",
      age: 24,
      rate: 90,
      community: "よく笑う人が好き",
      image:
        "https://images.unsplash.com/photo-1519742866993-66d3cfef4bbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=581&q=80"
    },
    {
      name: "OP",
      age: 25,
      rate: 40,
      community: "旅行大好き!",
      image:
        "https://images.unsplash.com/photo-1496840220025-4cbde0b9df65?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=668&q=80"
    }
  ]);
  const [currentUser, setCurrentUser] = React.useState(userList[0]);
  const [nextUser, setNextUser] = React.useState(userList[1]);
  const [isSwiped, setIsSwiped] = React.useState(false);

  const clickLike = () => {
    setIsSwiped(true);
    setTimeout(() => {
      setIsSwiped(false);
      setCurrentUser(nextUser);
      setNextUser(userList[2]);
      setUserList(userList.slice(1));
    }, 1000);
  };

  return (
    <div className="App">
      <h1 className="title">お相手からのいいね!</h1>
      <div className="card-container">
        {nextUser !== undefined ? (
          <Card
            name={nextUser.name}
            age={nextUser.age}
            rate={nextUser.rate}
            community={nextUser.community}
            image={nextUser.image}
            isSwiped={false}
          />
        ) : null}
        {currentUser !== undefined ? (
          <Card
            name={currentUser.name}
            age={currentUser.age}
            rate={currentUser.rate}
            community={currentUser.community}
            image={currentUser.image}
            isSwiped={isSwiped}
          />
        ) : null}
      </div>
      <div className="buttons">
        <button className="button-nope">
          <svg style={{ width: "40px", height: "40px" }} viewBox="0 0 24 24">
            <path
              fill="#cbced0"
              d="M10,9V5L3,12L10,19V14.9C15,14.9 18.5,16.5 21,20C20,15 17,10 10,9Z"
            />
          </svg>
        </button>
        <button className="button-like" onClick={clickLike}>
          <svg style={{ width: "28px", height: "28px" }} viewBox="0 0 24 24">
            <path
              fill="#f67272"
              d="M23,10C23,8.89 22.1,8 21,8H14.68L15.64,3.43C15.66,3.33 15.67,3.22 15.67,3.11C15.67,2.7 15.5,2.32 15.23,2.05L14.17,1L7.59,7.58C7.22,7.95 7,8.45 7,9V19A2,2 0 0,0 9,21H18C18.83,21 19.54,20.5 19.84,19.78L22.86,12.73C22.95,12.5 23,12.26 23,12V10M1,21H5V9H1V21Z"
            />
          </svg>
        </button>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

完成形はこちら!

https://codesandbox.io/embed/swipe-card-complete-yjlpo?codemirror=1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.