วิธีที่ถูกต้องในการจัดการข้อผิดพลาดใน React-Redux


11

ฉันต้องการที่จะเข้าใจว่าการจัดการข้อผิดพลาดทั่วไปหรือวิธีที่ถูกต้องมากขึ้นด้วย React-Redux คืออะไร

สมมติว่าฉันมีองค์ประกอบการลงทะเบียนหมายเลขโทรศัพท์

องค์ประกอบนั้นแจ้งว่าเกิดข้อผิดพลาดหากหมายเลขโทรศัพท์ที่ป้อนไม่ถูกต้อง

อะไรจะเป็นวิธีที่ดีที่สุดในการจัดการกับข้อผิดพลาดนั้น?

ความคิดที่ 1: สร้างองค์ประกอบซึ่งรับข้อผิดพลาดและยื้อการกระทำเมื่อใดก็ตามที่มีการส่งข้อผิดพลาดไป

ความคิดที่ 2: เนื่องจากข้อผิดพลาดเกี่ยวข้องกับส่วนประกอบนั้นส่งผ่านข้อผิดพลาดนั้นไปยังองค์ประกอบ (ซึ่งไม่ได้เชื่อมต่อกับ redux เช่นองค์ประกอบตัวจัดการข้อผิดพลาดจะไม่ส่งการกระทำ)

คำถาม:มีคนแนะนำฉันเกี่ยวกับวิธีการจัดการข้อผิดพลาดใน React-Redux สำหรับแอปขนาดใหญ่ได้หรือไม่?


1
การตรวจสอบหมายเลขโทรศัพท์เกิดขึ้นได้อย่างไรซิงโครนัสหรืออะซิงโครนัสหลังจากผู้ใช้ทำบางสิ่งหรือทันที คุณต้องการให้ผู้ใช้เห็นสิ่งใด Redux ใช้สำหรับจัดเก็บสถานะแอปของคุณดูเหมือนว่าไม่เกี่ยวข้องกับคำถามของคุณ
RemcoGerlich

คำตอบ:


3

ฉันจะบอกว่าไม่มีความคิดเริ่มต้นของคุณจับภาพรวมทั้งหมด แนวคิด 1 เป็นเพียงการติดต่อกลับ useCallbackหากคุณต้องการที่จะใช้โทรกลับ: แนวคิด 2 จะใช้งานได้และจะดีกว่าถ้าคุณไม่จำเป็นต้องใช้ redux บางครั้งคุณก็ควรใช้ redux บางทีคุณกำลังตั้งค่าความถูกต้องของแบบฟอร์มโดยการตรวจสอบว่าไม่มีฟิลด์อินพุตใดมีข้อผิดพลาดหรือสิ่งที่คล้ายกัน เนื่องจากเราอยู่ในหัวข้อของ redux ลองสมมติว่าเป็นกรณีนี้

โดยปกติแล้ววิธีที่ดีที่สุดในการจัดการข้อผิดพลาดด้วย redux คือการมีฟิลด์ข้อผิดพลาดในสถานะที่ถูกส่งผ่านไปยังองค์ประกอบข้อผิดพลาด

const ExampleErrorComponent= () => {
  const error = useSelector(selectError);
  if (!error) return null;
  return <div className="error-message">{error}</div>;
}

useEffectองค์ประกอบข้อผิดพลาดที่ไม่ได้มีเพียงแค่แสดงข้อผิดพลาดก็ยังสามารถทำผลข้างเคียงด้วย

วิธีการตั้งค่า / unset ข้อผิดพลาดขึ้นอยู่กับแอปพลิเคชันของคุณ ลองใช้ตัวอย่างหมายเลขโทรศัพท์ของคุณ

1. ถ้าการตรวจสอบความถูกต้องเป็นฟังก์ชั่นที่บริสุทธิ์สามารถทำได้ในตัวลด

จากนั้นคุณจะตั้งค่าหรือยกเลิกการตั้งค่าฟิลด์ข้อผิดพลาดเพื่อตอบสนองต่อการดำเนินการเปลี่ยนแปลงหมายเลขโทรศัพท์ ในตัวลดที่สร้างขึ้นด้วยคำสั่งเปลี่ยนมันอาจมีลักษณะเช่นนี้

case 'PHONE_NUMBER_CHANGE':
  return {
    ...state,
    phoneNumber: action.phoneNumber,
    error: isValidPhoneNumber(action.phoneNumber) ? undefined : 'Invalid phone number',
  };

2. ถ้ามีการรายงานข้อผิดพลาดโดยแบ็กเอนด์ส่งการกระทำผิดพลาด

สมมติว่าคุณกำลังส่งหมายเลขโทรศัพท์ไปยังแบ็กเอนด์ที่ตรวจสอบความถูกต้องก่อนที่จะทำอะไรกับหมายเลขนั้น คุณไม่สามารถทราบได้ว่าข้อมูลนั้นถูกต้องในฝั่งไคลเอ็นต์หรือไม่ คุณจะต้องใช้คำของเซิร์ฟเวอร์สำหรับมัน

const handleSubmit = useCallback(
  () => sendPhoneNumber(phoneNumber)
    .then(response => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_SUCCESS',
      response,
    }))
    .catch(error => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_FAILURE',
      error,
    })),
  [dispatch, phoneNumber],
);

ตัวลดจะเกิดขึ้นพร้อมกับข้อความที่เหมาะสมสำหรับข้อผิดพลาดและตั้งค่า

อย่าลืมล้างข้อผิดพลาด คุณสามารถยกเลิกข้อผิดพลาดในการดำเนินการเปลี่ยนแปลงหรือเมื่อทำการร้องขออื่นขึ้นอยู่กับแอปพลิเคชัน

วิธีการทั้งสองที่ฉันระบุไว้ไม่เป็นเอกสิทธิ์เฉพาะบุคคล คุณสามารถใช้ข้อแรกเพื่อแสดงข้อผิดพลาดที่ตรวจพบภายในเครื่องและใช้ข้อที่สองเพื่อแสดงข้อผิดพลาดด้านเซิร์ฟเวอร์หรือเครือข่าย


ฉันซาบซึ้งในคำตอบของคุณและนี่เป็นวิธีที่ดีกว่าเมื่อเทียบกับสิ่งที่ฉันทำ ฉันยังคงมองหาข้อเสนอแนะเพิ่มเติมและด้วยเหตุนี้ฉันจึงเริ่มรับรางวัลสำหรับคำถามนี้
anny123

1

ฉันจะใช้ formik กับการตรวจสอบ yup จากนั้นสำหรับข้อผิดพลาดฝั่งเซิร์ฟเวอร์ฉันจะใช้สิ่งนี้:

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Spinner } from "@blueprintjs/core";

export default ({ action, selector, component, errorComponent }) => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(action());
  }, [dispatch, action]);

  const DispatchFetch = () => {
    const { data, isRequesting, error } = useSelector(selector());
    if (!isRequesting && data) {
      const Comp = component;
      return <Comp data={data}></Comp>;
    } else if (error) {
      if (errorComponent) {
        const ErrorComp = errorComponent;
        return <ErrorComp error={error}></ErrorComp>;
      }
      return <div>{error}</div>;
    }
    return <Spinner></Spinner>;
  };

  return <DispatchFetch></DispatchFetch>;
};

ดูเหมือน anerco ที่น่าสนใจขอขอบคุณที่ตอบ :) :)
anny123

1

ขึ้นอยู่กับชนิดของการจัดการข้อผิดพลาดที่คุณกำลังพูดถึง ถ้ามันเป็นเพียงการตรวจสอบรูปแบบการจัดการแล้วผมไม่คิดว่าคุณต้อง Redux ที่ - โปรดอ่านบทความนี้ หากข้อผิดพลาดของคุณกำลังจะ "สิ้นเปลือง" ภายในองค์ประกอบนั้นทำไมส่งไปที่ redux คุณสามารถใช้สถานะท้องถิ่นของคุณได้อย่างง่ายดาย

ในทางตรงกันข้ามหากคุณต้องการแสดงการแจ้งเตือนข้อผิดพลาดบางอย่างแก่ผู้ใช้ระบุว่าการเรียก HTTP บนไซต์ล้มเหลวคุณสามารถได้รับประโยชน์จาก redux โดยการส่งข้อผิดพลาดจากทุกส่วนของแอปพลิเคชันของคุณ

dispatch({ type: 'SET_ERROR_MESSAGE', error: yourErrorOrMessage });

// simple error message reducer
function errorMessage(state = null, action) {
  const { type, error } = action;

  switch (type) {
      case 'RESET_ERROR_MESSAGE':
          return null;
      case 'SET_ERROR_MESSAGE':
          return error;
  }

  return state
}

คุณต้องกำหนดว่ารัฐของคุณจะถูกจัดระเบียบอย่างไรและไม่ว่าคุณจะต้องใส่สถานะใน redux หรือเพียงแค่เก็บไว้ในสถานะท้องถิ่นขององค์ประกอบของคุณ คุณสามารถใส่ทุกสิ่งทุกอย่างใน redux ได้ แต่โดยส่วนตัวฉันจะบอกว่ามันเป็น overkill - ทำไมคุณถึงใส่ state X ใน component Y ถ้า component Y เท่านั้นที่ใส่ใจเกี่ยวกับสถานะนั้น หากคุณจัดโครงสร้างรหัสของคุณอย่างถูกต้องคุณไม่ควรมีปัญหากับการย้ายสถานะนั้นจากโลคัลไปยังเรดจ์ในภายหลังถ้าด้วยเหตุผลบางอย่างส่วนอื่น ๆ ของแอพของคุณเริ่มพึ่งพาสถานะนั้น


1

ฉันคิดเกี่ยวกับสิ่งนี้สิ่งที่ควรจะเป็นรัฐ? และสิ่งที่ควรได้รับจากรัฐ? รัฐควรเก็บไว้ใน redux และการคำนวณควรจะคำนวณ

หมายเลขโทรศัพท์คือสถานะฟิลด์ใดมีโฟกัสเป็นสถานะ แต่ไม่ว่าจะถูกต้องหรือไม่นั้นสามารถได้มาจากค่าในสถานะ

ฉันจะใช้ Reselect เพื่อแคช derivations และส่งคืนผลลัพธ์เดียวกันเมื่อสถานะที่เกี่ยวข้องไม่ได้รับการแก้ไข

export const showInvalidPhoneNumberMessage = createSelector(
  getPhoneValue,
  getFocusedField,
  (val, focus) => focus !== 'phone' && val.length < 10 // add other validations.
)

จากนั้นคุณสามารถใช้ตัวเลือกใน mapStateToProps ในองค์ประกอบทั้งหมดที่อาจสนใจเกี่ยวกับค่านี้และคุณสามารถใช้มันในการดำเนินการ async ได้เช่นกัน หากไม่ได้เปลี่ยนโฟกัสหรือค่าของฟิลด์ไม่เปลี่ยนแปลงการคำนวณใหม่จะไม่เกิดขึ้นมันจะคืนค่าก่อนหน้าแทน

ฉันกำลังเพิ่มการตรวจสอบสถานะที่เลือกไว้เพียงเพื่อแสดงให้เห็นว่ารัฐหลายชิ้นสามารถมารวมกันเพื่อให้ได้มาหนึ่งครั้ง

โดยส่วนตัวฉันพยายามเข้าใกล้สิ่งต่าง ๆ โดยทำให้สถานะของฉันเล็กที่สุดเท่าที่จะทำได้ ตัวอย่างเช่นสมมติว่าคุณต้องการสร้างปฏิทินของคุณเอง คุณจะเก็บทุกวันในสถานะหรือคุณเพียงแค่ต้องรู้บางสิ่งบางอย่างเช่นปีปัจจุบันและเดือนที่กำลังดูอยู่ ด้วยสถานะเพียง 2 ชิ้นนี้คุณสามารถคำนวณวันที่จะแสดงบนปฏิทินและไม่จำเป็นต้องคำนวณใหม่จนกว่าจะมีการเปลี่ยนแปลงอย่างใดอย่างหนึ่งและการคำนวณใหม่นี้จะเกิดขึ้นโดยอัตโนมัติแทบไม่จำเป็นต้องคิดวิธีที่พวกเขาสามารถทำได้ เปลี่ยนแปลง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.