1
3

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 Native】FlatListを使ってTab Barを作る

Last updated at Posted at 2021-06-22

自分用の備忘録です(編集中の箇所あり)

=====================
以下の動画に沿って React Native で Tab Bar の作成したので、手順をまとめます。
React Native: Custom Tab Radio & Filter List Data

####インポート

import React from "react";
import {
 Text,
 StyleSheet,
 View,
 Image,
 TextInput,
 Dimensions,
 FlatList,
 TouchableOpacity,
 TouchableOpacityComponent,
} from "react-native";

Step1 : タブボタンを作る

image.png
const Practice = () => {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        <TouchableOpacity style={styles.btnTab}>
         <Text style={styles.textTab}>All</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};
export default Practice;

CSS

const styles = StyleSheet.create({
  container: {
    justifyContent: "center",
    backgroundColor: "#fff",
    padding: 15,
  },

  listTab: {
    flexDirection: "row",
    alignSelf: "center",
    marginBottom: 20,
  },
  btnTab: {
    width: Dimensions.get("window").width / 3,
    flexDirection: "row",
    borderWidth: 0.5,
    borderColor: "#ebebeb",
    padding: 10,
    justifyContent: "center",
  },
  textTab: {
    fontSize: 16,
  },
});

Step2 : タブボタンを複数にする

image.png

① タブボタンの定義

const listTab = [
  {
    status: "All",
  },
  {
    status: "Purple",
  },
  {
    status: "Green",
  },
];

② 定義したタブボタンをループで表示

const Practice = () => {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
    //配列をループ表示  ここから
        {
        listTab.map((e) => (
          <TouchableOpacity style={styles.btnTab}>
            <Text style={styles.textTab}>{e.status}</Text>
          </TouchableOpacity>
        ))
        }
        //ここまで
      </View>
    </SafeAreaView>
  );
};

.map で配列要素をループで表示することができます

##Step3 : ボタンをクリックした時にボタンの色を変化させる(状態変化)
背景がピンク、文字が白になるようにします。
image.png

useStateを使用

Stateは コンポーネントの状態を表すデータ です。状態ですので、状況によって値が変化します。
Stateでコンポーネントの状態を管理する

useState によって React の state の機能を関数コンポーネントに追加できます。
React

① useStateをインポート

import React, { useState } from "react";

② stateの初期値を設定

const Practice = () => {
  //初期値を"All"にセット ここから
  const [status, setStatus] = useState("All");
  //ここまで
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        {listTab.map((e) => (
          <TouchableOpacity 
          style={styles.btnTab}>
            <Text style={styles.textTab}>{e.status}</Text>
          </TouchableOpacity>
        ))}
      </View>
    </SafeAreaView>
  );
};

useStateでは、現在の state(状態) と、それを更新するための関数とを、ペアにして返します。
上記のconst [status, setStatus] の場合、statusという名前の state 変数を宣言しており、初期値ではそれを"All"にセットしています。現在の status の値を更新したい場合は、setStatus を呼ぶことができます。

参考:React

③ ボタンにイベントを設定

onPressでイベントを設定

const Practice = () => {
  const [status, setStatus] = useState("All");
//ファンクションを定義(内容はStep5で) ここから
  const setStatusFilter = (status) => {
    setStatus(status);
//ここまで
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        {listTab.map((e) => (
          <TouchableOpacity
            style={styles.btnTab}
//[onPress] クリックするとイベント(setFunctionFilter)が発生  ここから
            onPress={() => setStatusFilter(e.status)}
//ここまで
          >
            <Text style={styles.textTab}>{e.status}</Text>
          </TouchableOpacity>
        ))}
      </View>
    </SafeAreaView>
  );
};

setFunctionFilterのファンクションの中身は後で作ります

④ ボタンをクリックした時に色が変化するよう設定

return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        {listTab.map((e) => (
          <TouchableOpacity
          //クリックしたボタンにbtnTabActiveのスタイルが適用される、背景ピンクになる ここから
            style={[styles.btnTab, status === e.status && styles.btnTabActive]}
          //ここまで
            onPress={() => setStatusFilter(e.status)}
          >
            <Text
            //クリックしたボタンにbtnTextActiveのスタイルが適用される、文字が白になる ここから
              style={[
                styles.textTab,
                status === e.status && styles.textTabActive,
              ]}
            //ここまで
            >
              {e.status}
            </Text>
          </TouchableOpacity>
        ))}
      </View>
    </SafeAreaView>
  );
};

CSS

  btnTabActive: {
    backgroundColor: "#e6838d",
  },

  textTabActive: {
    color: "#fff",
  },

##Step4 : リストを表示する
アイテムリストを並べただけ(ボタンを押してもまだ表示は変わりません)
image.png

FlatListを使用

① リストデータを作成

const listTab = [
  {
    status: "All",
  },
  {
    status: "Purple",
  },
  {
    status: "Green",
  },
];

//データ作成 ここから
const data = [
  {
    name: "Ronaldo",
    status: "Green",
  },
  {
    name: "Messi",
    status: "Purple",
  },
  {
    name: "Kaka",
    status: "Green",
  },
  {
    name: "Mbappe",
    status: "Green",
  },
  {
    name: "Lukakau",
    status: "Purple",
  },
];
//ここまで

② リストを表示

const Practice = () => {
  const [status, setStatus] = useState("All");
  const setStatusFilter = (status) => {
    setStatus(status);
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        {listTab.map((e) => (
          <TouchableOpacity
            style={[styles.btnTab, status === e.status && styles.btnTabActive]}
            onPress={() => setStatusFilter(e.status)}
          >
            <Text
              style={[
                styles.textTab,
                status === e.status && styles.textTabActive,
              ]}
            >
              {e.status}
            </Text>
          </TouchableOpacity>
        ))}
      </View>

     //FlatList ここから
      <FlatList
        data={datalist}
        keyExtractor={(e, i) => i.toString()}
        renderItem={renderItem}
      />
     //ここまで

    </SafeAreaView>
  );
};

③ レンダリングする

const Practice = () => {
  const [status, setStatus] = useState("All");
  const setStatusFilter = (status) => {
    setStatus(status);
  };

//レンダリング  ここから追記
  const renderItem = ({ item, index }) => {
    return (
      <View key={index} style={styles.itemContainer}>
        <View style={styles.itemLogo}>
          <Image
            style={styles.itemImage}
            source={{
              uri: "https://store.juventus.com/data/store/product/2/26919/product.jpg",
            }}
          />
        </View>

        <View style={styles.itemBody}>
          <Text style={styles.itemName}>{item.name}</Text>
        </View>

        <View
          style={[
            styles.itemStatus,
            {
              backgroundColor: item.status === "Purple" ? "#e5848e" : "#69C080",
            },
          ]}
        >
          <Text>{item.status}</Text>
        </View>
      </View>
    );
  };
//ここまで

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.listTab}>
        {listTab.map((e) => (
          <TouchableOpacity
            style={[styles.btnTab, status === e.status && styles.btnTabActive]}
            onPress={() => setStatusFilter(e.status)}
          >
            <Text
              style={[
                styles.textTab,
                status === e.status && styles.textTabActive,
              ]}
            >
              {e.status}
            </Text>
          </TouchableOpacity>
        ))}
      </View>

      <FlatList
        data={data}
        keyExtractor={(e, i) => i.toString()}
        renderItem={renderItem}
      />
    </SafeAreaView>
  );
};

CSS

  itemContainer: {
    flexDirection: "row",
    paddingVertical: 15,
  },

  itemLogo: {
    padding: 10,
  },

  itemImage: {
    width: 50,
    height: 50,
  },
  itemBody: {
    flex: 1,
    paddingHorizontal: 10,
    justifyContent: "center",
  },
  itemName: {
    fontWeight: "bold",
    fontSize: 16,
  },
  itemStatus: {
    backgroundColor: "green",
    paddingHorizontal: 6,
    justifyContent: "center",
    right: 12,
  },

##Step5 : ボタンをクリックした時に表示リストを変化させる(状態変化)
Purpleのボタンを押すと「Purple」のカテゴリが、Greenを押すと「Green」が表示されるようにします
image.png
image.png

① useStateを設定

const [status, setStatus] = useState("All");の下に記述

  const [datalist, setDatalist] = useState(data);

setFunctionFilterファンクションの中身を作成

const setStatusFilter = (status) => {
    //statusが"All"以外だったら(Purple and Greenなら)
    if (status !== "All") {
    //filterメソッドで、特定カテゴリのデータが表示される(何が起きているかわからんんん)
      setDatalist([...data.filter((e) => e.status === status)]);
    //"All"の場合は全リスト表示
    } else {
      setDatalist(data);
    }
    setStatus(status);
  };

...data... は「スプレッド構文(Spread Syntax)」と言われ、配列やオブジェクトの要素を展開する構文です。
ここでは、Step4 で定義したリストデータ data の中身↓が展開されています。

const data = [
  {
    name: "Ronaldo",
    status: "Green",
  },
  {
    name: "Messi",
    status: "Purple",
  },
  {
    name: "Kaka",
    status: "Green",
  },
  {
    name: "Mbappe",
    status: "Green",
  },
  {
    name: "Lukakau",
    status: "Purple",
  },
];

参考:JSのスプレッド構文を理解する

<FlatList />の data の中身を datalist に書き換え

      <FlatList
        data={datalist}  //ここを書き換え
        keyExtractor={(e, i) => i.toString()}
        renderItem={renderItem}
      />

④ item separator を設定(オプション)

よくわからない

  const separator = () => {
    return <View style={{ height: 1, backgroundColor: "#f1f1f1" }} />;
  };
  <FlatList
   data={datalist}
   keyExtractor={(e, i) => i.toString()}
   renderItem={renderItem}
   ItemSeparatorComponent={separator} //ここを追記
  />

以上。
のちほど再編集していきます。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?