cp716716
@cp716716

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【React Native + Expo】useContextとuseReducerの利用方法について②

Qiita初心者です。
誤字脱字、至らない点があるかもしれませんがよろしくお願いします。

以前上記で質問をさせていただきましたが、追加で不明点が出てきました。

解決したいこと

React Native + Expoでスマホアプリをつくっています。
hooksのuseContextとuseReducerを使用し
グローバルな値をどのコンポーネントでも更新、取得ができるようにしたいです。

以下キャプチャの画面より、左右の矢印を押して日付を変更すると、
日付表示が変わり、その日に飲んだミルクの合計量を表示させたいです。
IMG_3443.PNG

DBはFireBaseを使用しており、データ構造は以下となります
スクリーンショット 2022-12-23 16.25.48.png

わからないこと

日付変更は既にhooksを使用しデータの更新や取得ができていますが、
DB上にある配列データの取得と更新方法がわかりません

【不明点①】
初期値の設定方法(当日のミルク合計値を設定)
※TestContext.jsxのconst dataまではデータが取得できていることをログで確認していますが、そこからstateへの設定方法がわかりません

【不明点②】
日付を変更した際に、変更後の日付でミルクの合計値を再取得し表示

React Nativeも初心者なもので、
解決策についてご教示いただけましたら幸いです。

また、以下記事を参考にさせていただきました。

該当のコード

【階層】
スクリーンショット 2022-12-16 17.14.56.png

【親コンポーネント】

TestScreen.jsx
import React from 'react';
import { View } from 'react-native';

import TestComponent from '../components/TestComponent';
import { CountProvider } from '../context/TestContext';

export default function TestScreen() {
    
    return (
        <CountProvider>
            <View>
                < TestComponent />
            </View>
        </CountProvider>
    );
}

【子コンポーネント】

TestComponent.jsx
import React from 'react';
import firebase from 'firebase';

import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { useTestContext } from '../context/TestContext';
export default function TestComponent() {
    const { state, dispatch } = useTestContext();
    const dayOfWeek = [ "", "", "", "", "", "", "" ] ;

    return (
        <View>
            <View style={styles.date}>
                <TouchableOpacity
                    onPress={ () => dispatch({
                        type: "decrement",
                        year: state.year,
                        month: state.month,
                        day: state.day,
                        youbiCount: state.youbiCount
                    })} style={styles.dateText}>
                    <Text style={styles.cursorText}>◀︎</Text>    
                </TouchableOpacity>
                <Text style={styles.dateText}>
                    {state.year}{state.month}{state.day}日({dayOfWeek[state.youbiCount]})
                </Text>
                <TouchableOpacity
                    onPress={ () => dispatch({
                        type: "increment",
                        year: state.year,
                        month: state.month,
                        day: state.day,
                        youbiCount: state.youbiCount
                    })} style={styles.dateText}>
                    <Text style={styles.cursorText}>▶︎</Text>
                </TouchableOpacity>
            </View>
            <View style={styles.date}>
                <Text>飲んだmilkの合計量 → "○○"ml</Text>
            </View>
        </View>
    )
};

const styles = StyleSheet.create({
    date: {
        flexDirection: 'row',
        height: 70,
        alignItems:'center',
        justifyContent: 'center',
    },
    dateText: {
        fontSize: 20,
        paddingHorizontal: 10,
    },
    cursorText: {
        fontSize: 40,
    },
});

【Contextファイル】

TestContext.jsx
import React, { createContext, useReducer, useContext}  from 'react';
import firebase from 'firebase';

//========
// Context
//========
const TestContext = createContext();

export function useTestContext() {
  return useContext(TestContext);
}


export function CountProvider({ children }) {

  //========
  // 初期値設定
  //========
  const date = new Date(Math.floor(new Date().getTime()/1000/60/5)*1000*60*5);

  const db =firebase.firestore();
  const { currentUser } = firebase.auth();

  const initialState = {
    year: Number(date.getFullYear()),
    month: Number(date.getMonth() + 1),
    day: Number(date.getDate()),
    hours: Number(date.getHours()),
    minutes: Number(date.getMinutes()),
    youbiCount: Number(date.getDay()),
  };

  //ここからわからない=====================

  //========
  // DB接続、値取得
  //========
  let unsubscribe = () => {};
  if (currentUser) {
      const ref = db.collection(`users/${currentUser.uid}/${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`).orderBy('updatedAt', 'asc');
      unsubscribe = ref.onSnapshot((snapshot) => {
                snapshot.forEach((doc) => {
                    const data = doc.data();
          });
      }, (error) => {
          console.log(error);
          Alert.alert('データの読み込みに失敗しました。');
      });
  }
  //=====================ここまでわからない
  
  const reducer = (state, action) => {

    let endDate = new Date(action.year, action.month, 0) // 月の最後の日を取得
    let endDayCount = endDate.getDate() // 月の末日

    //========
    // 日付変更処理
    //========
    if (action.type == "increment") {
      if (action.day != null) {
        state.day = action.day + 1;
        state.youbiCount = action.youbiCount + 1;
        //末日の場合は翌月の1日に設定する
        if (state.day > endDayCount) {
          state.day = 1;
          if (action.month < 12) {
            state.month = action.month + 1;
          } else if (action.month = 12){
            state.month =  1;
            state.year = action.year + 1;
          }
        };
        //土曜日の場合は日曜日に設定
        if (state.youbiCount >= 7) {
          state.youbiCount = 0;
        }
      };
    } else if (action.type == "decrement") {
      if (action.day != null) {
        state.day = action.day - 1;
        state.youbiCount = action.youbiCount - 1;
        // 前の月の場合は前月の末尾を取得する
        if (state.day < 1) {
          endDate = new Date(action.year, action.month-1, 0) // 前月の最後の日を取得
          endDayCount = endDate.getDate() // 前月の末日
          state.day = endDayCount;
          if (action.month > 1) {
            state.month = action.month - 1;
          } else if (action.month = 1){
            state.month = 12;
            state.year = action.year - 1;
          }
        }
        //日曜日の場合は土曜日に戻る
        if (state.youbiCount <= -1) {
          state.youbiCount = 6;
        }
      };
    };

    //========
    // 時間変更処理
    //========
    if (action.type == "timeUpdate") {
      if (action.hours != null && action.minutes != null ) {
        state.hours = action.hours;
        state.minutes = action.minutes;
      };
    };

    return {
      year: state.year,
      month: state.month,
      day: state.day,
      hours: state.hours,
      minutes: state.minutes,
      youbiCount: state.youbiCount,
      memos: state.memos,
      unsubscribe,
    };
  };

  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <TestContext.Provider value={{state, dispatch}}>
      {children}
    </TestContext.Provider>
  );
  
}

よろしくお願いいたします。

0

No Answers yet.

Your answer might help someone💌