0

アプリ全体で再利用するカスタム フックを作成していますが、コード内のコメントからわかるように、予期しない結果が得られました。 console.log しかし、それらは2回ディスパッチされ、状態の値を取得しようとしたときに、いくつかのアクションをディスパッチした後、期待される状態を取得できませんでした。デフォルトのものを取得しました。

import { useReducer, useCallback, useState } from "react";
import { functions } from "../base";
const initialState = {
  to: [],
  cc: [],
  bcc: [],
  data: {},
  subject: "",
};
const SET_RECIEPENTS = "SET_RECIEPENTS";
const ADD_RECIEPENT = "ADD_RECIEPENT";
const SET_SUBJECT = "SET_SUBJECT";
const SET_CC = "SET_CC";
const ADD_CC = "ADD_CC";
const SET_BCC = "SET_BCC";
const ADD_BCC = "ADD_BCC";
const SET_DATA = "SET_DATA";
const RESET = "RESET";
const emailReducer = (state, action) => {
  console.log("prevState: ", state); // logs state
  console.log("action: ", action); // called twice with the expected type and payload and triggers state change
  switch (action.type) {
    case SET_RECIEPENTS:
      if (!action.reciepents instanceof Array) {
        throw new Error("reciepents must be an Array");
      }
      return {
        ...state,
        to: [...action.reciepents],
      };
    case ADD_RECIEPENT:
      if (typeof action.reciepent !== "string" || action.reciepent === "") {
        throw new Error("the reciepent must be a string");
      }
      return { ...state, to: [...state.to, action.reciepent] };
    case SET_SUBJECT:
      if (typeof action.subject !== "string" || action.subject === "") {
        throw new Error("Subject must be a string");
      }
      return {
        ...state,
        subject: action.subject,
      };
    case SET_CC:
      if (!action.cc instanceof Array) throw new Error("CC must be an Array");
      return {
        ...state,
        cc: [...action.cc],
      };
    case ADD_CC:
      if (typeof action.cc !== "string" || action.cc === "") {
        throw new Error("the CC must be a string");
      }
      return {
        ...state,
        cc: [...state.cc, action.cc],
      };
    case SET_BCC:
      if (!action.bcc instanceof Array) throw new Error("BCC must be an Array");
      return {
        ...state,
        bcc: [...action.bcc],
      };
    case ADD_BCC:
      if (typeof action.bcc !== "string" || action.bcc === "") {
        throw new Error("the BCC must be a string");
      }
      return {
        ...state,
        bcc: [...state.bcc, action.bcc],
      };
    case SET_DATA:
      if (typeof action.data !== "object") {
        throw new Error("Data must be a object");
      }
      return {
        ...state,
        data: { ...action.data },
      };
    case RESET:
      return { ...initialState };
    default:
      throw new Error(`Unhandled action type: ${action.type}`);
  }
};
const useSendEmail = (templateId, cb = function () {}) => {
  if (!templateId || templateId === "" || typeof templateId !== "string") {
    throw new Error("please provide a valid template id");
  }
  const [state, dispatch] = useReducer(emailReducer, initialState);
  const [error, setError] = useState(null);
  const { to } = state;
  const setReciepents = useCallback(
    (reciepents) => dispatch({ type: SET_RECIEPENTS, reciepents }),
    []
  );
  const addReciepent = useCallback(
    (reciepent) => dispatch({ type: ADD_RECIEPENT, reciepent }),
    []
  );
  const setSubject = useCallback(
    (subject) => dispatch({ type: SET_SUBJECT, subject }),
    []
  );
  const setCC = useCallback((cc) => dispatch({ type: SET_CC, cc }), []);
  const addCC = useCallback((cc) => dispatch({ type: ADD_CC, cc }), []);
  const setBCC = useCallback((bcc) => dispatch({ type: SET_BCC, bcc }), []);
  const addBCC = useCallback((bcc) => dispatch({ type: ADD_BCC, bcc }), []);
  const setData = useCallback((data) => dispatch({ type: SET_DATA, data }), []);
  const reset = useCallback(() => dispatch({ type: RESET }), []);
  const sendEmail = useCallback(() => {
     console.log({state}) // returns the default state
    if (to && to.length > 1) {
     console.log({state}) // never runs becuase there aren't emails in to []
      try {
        const sendEmailFunction = functions.httpsCallable().sendEmail;
        sendEmailFunction({ ...state, templateId })
          .then(() => {
            cb({ ...state });
          })
          .catch((err) => {
            setError(err);
          });
      } catch (err) {
        setError(err);
      }
    }
  }, []);
  return {
    setReciepents,
    addReciepent,
    setSubject,
    setCC,
    addCC,
    setBCC,
    addBCC,
    setData,
    reset,
    sendEmail,
    error,
  };
};
export default useSendEmail;

コンポーネントでは、このフックコードを使用しました

 const {
    sendEmail,
    error,
    addReciepent,
    addCC,
    addBCC,
    setSubject,
    setData,
  } = useSendEmail("ID", () => {
    setSucces(true);
  });

    const handleAddEmail = () => {
    if (email !== "") {
      setEmailsList((list) => [...list, email]);
      addReciepent(email);
      setEmail("");
    }
  };

  const handleAddCC = () => {
    if (cc !== "") {
      setCCList((list) => [...list, cc]);
      addCC(cc);
      setCCValue("");
    }
  };

  const handleAddBCC = () => {
    if (bcc !== "") {
      setBCCList((list) => [...list, bcc]);
      addBCC(bcc);
      setBCCValue("");
    }
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    console.log("Submit");
    setSubject(subject);
    setData({ name, place });
    sendEmail();
  };

私は本当にこのカスタムフックアプローチを続けたいと思っていますが、これらのバグは誰かが助けてくれることを本当に願っています. ありがとう

4

1 に答える 1