對於下拉框的資料獲取,需要單獨拆分出一個hooks嗎

龙陌發表於2024-03-16

對於下拉框的資料獲取,是否需要單獨拆分出一個hook取決於專案的具體需求和程式碼組織結構。以下是一些考慮因素:

  1. 複用性

    • 如果專案中多個地方都需要從同一個API或者同一個資料來源獲取下拉框選項資料,並且處理邏輯相同,那麼建立一個專門的hooks用於獲取並處理下拉框資料是合理的。這樣可以避免程式碼重複,提高程式碼可讀性和維護性。
  2. 非同步載入與快取

    • 如果下拉框資料是從後端非同步獲取,並且可能頻繁請求,那麼將資料獲取封裝成一個hook,內部包含非同步請求、錯誤處理、以及快取機制(如使用useMemouseRef來儲存已獲取過的資料),有助於最佳化效能和使用者體驗。
  3. 業務邏輯複雜度

    • 如果獲取下拉框資料涉及複雜的業務邏輯,比如需要根據其他狀態變數動態查詢不同的資料來源,或者資料轉換過程比較複雜,那麼封裝成一個獨立的hook可以讓這部分邏輯更易於管理。

示例程式碼(基於React Hooks):

import { useState, useEffect } from 'react';

// 假設有個API介面返回下拉框選項列表
const fetchOptions = () => axios.get('/api/options');

function useDropdownOptions() {
  const [options, setOptions] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let didCancel = false;

    async function fetchData() {
      try {
        setLoading(true);
        const response = await fetchOptions();
        if (!didCancel) {
          setOptions(response.data);
          setLoading(false);
        }
      } catch (err) {
        if (!didCancel) {
          setError(err);
          setLoading(false);
        }
      }
    }

    fetchData();

    // 清理函式,防止元件解除安裝時仍有網路請求
    return () => {
      didCancel = true;
    };
  }, []); // 空依賴陣列確保只在元件掛載時執行一次

  return { options, loading, error };
}

// 使用該hook
function DropdownComponent() {
  const { options, loading, error } = useDropdownOptions();

  // 根據loading和error狀態展示合適的UI
  // 並將options傳遞給下拉框元件進行渲染
  
  return (
    <select>
      {loading ? <option>Loading...</option> : null}
      {error ? <option>Error fetching data</option> : null}
      {options.map(option => (
        <option key={option.id} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

總之,在合適的情況下,為下拉框資料獲取建立一個自定義hook可以幫助提升程式碼的模組化程度,簡化資料處理流程,並便於後期維護和擴充套件。

如果需要在下拉框獲取到值後,更新某個表單項的欄位或者進行計算,展示計算後的結果,應該如何修改上述程式碼

如果在下拉框獲取到值後,需要更新某個表單項的欄位或者進行計算,並展示計算後的結果,可以對上述程式碼進行如下修改:

首先,在自定義hook useDropdownOptions 中新增一個回撥函式,用於接收選中的選項值並觸發相關的狀態更新或計算邏輯。

function useDropdownOptions(callbackOnSelect) {
  // ...(保持原有的資料獲取和狀態管理不變)

  // 新增一個處理選擇事件的方法
  const handleSelect = (selectedValue) => {
    callbackOnSelect(selectedValue);
  };

  return { options, loading, error, handleSelect };
}

// 使用該hook時傳入一個處理選中值的回撥函式
function DropdownComponent() {
  const { options, loading, error, handleSelect } = useDropdownOptions((selectedValue) => {
    // 在這裡處理選中值,比如更新表單項狀態或進行計算
    updateFormField(selectedValue);
    performCalculation(selectedValue);
  });

  // 下拉框元件的onChange事件繫結handleSelect方法
  const handleChange = (event) => {
    handleSelect(event.target.value);
  };

  // ...
  
  return (
    <select value={selectedOption} onChange={handleChange}>
      {/* 下拉框選項 */}
    </select>
  );
}

同時,根據實際需求定義updateFormFieldperformCalculation等函式來更新表單欄位和執行計算操作。這些函式可以在DropdownComponent內部定義,也可以提取到更高層級以便複用。

// 示例:更新表單項狀態
const [formField, setFormField] = useState(null);

const updateFormField = (value) => {
  setFormField(value);
};

// 示例:執行計算
const performCalculation = (selectedValue) => {
  // 根據selectedValue進行計算,並將結果顯示在UI上
  const calculatedResult = calculateSomething(selectedValue);
  // 更新顯示計算結果的狀態
  setCalculatedResult(calculatedResult);
};

這樣,在下拉框選項發生變化時,不僅可以更新表單欄位,還可以實時執行相關計算並展示計算結果。

初始化渲染第一次獲取到下拉框資料的時候,會觸發選項變化的事件嗎?

初始化渲染時獲取到下拉框資料並不會自動觸發選項變化的事件。在React中,元件首次渲染時設定的初始狀態不會觸發onChange等事件處理函式。

通常,onChange事件是在使用者互動(如選擇下拉框中的一個新選項)後觸發的。如果需要在首次獲取到下拉框資料後執行某些邏輯,可以在獲取資料後透過useEffect或其他生命週期鉤子手動處理:

function DropdownComponent() {
  const [options, setOptions] = useState([]);
  const [selectedOption, setSelectedOption] = useState(null);

  useEffect(() => {
    async function fetchOptions() {
      // 獲取下拉框選項資料
      const fetchedOptions = await getDropdownOptions();
      
      // 設定初始選項資料
      setOptions(fetchedOptions);

      // 如果有預設選項需要選中,這裡可以設定
      if (fetchedOptions.length > 0) {
        setSelectedOption(fetchedOptions[0].value); // 假設第一個是預設值
      }
      
      // 在首次獲取資料後執行特定操作
      handleInitialSelection();
    }

    fetchOptions();
  }, []); // 空依賴陣列確保只在掛載時執行一次

  // 處理選項變化的事件
  const handleSelectChange = (event) => {
    setSelectedOption(event.target.value);
    // 其他處理邏輯...
  };

  // 首次獲取資料後的操作
  const handleInitialSelection = () => {
    // 根據首次獲取的資料進行相關計算或更新表單欄位等操作
    performCalculation(selectedOption);
    updateFormField(selectedOption);
  };

  return (
    <select value={selectedOption} onChange={handleSelectChange}>
      {options.map(option => (
        <option key={option.id} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

在這個例子中,我們透過useEffect在首次載入時獲取並設定下拉框選項,並在設定了初始選項後呼叫handleInitialSelection來執行相應的計算和更新操作。
handleSelectChange方法則會在實際使用者互動改變下拉框選項時被呼叫。

這種情況下,是否沒辦法將獲取下拉框資料抽成hooks?

實際上,即使在初始化渲染時需要處理獲取到的下拉框資料,並執行特定邏輯(如更新表單項或進行計算),依然可以將獲取下拉框資料的部分抽成一個hook。關鍵在於如何設計和使用這個hook。

以下是一個例子:

// 建立一個自定義hook來獲取下拉框資料
function useDropdownOptions(initialSelectedValue) {
  const [options, setOptions] = useState([]);
  const [selectedOption, setSelectedOption] = useState(initialSelectedValue);

  useEffect(() => {
    async function fetchOptions() {
      const fetchedOptions = await getDropdownOptions();
      setOptions(fetchedOptions);
      
      // 如果有預設選項需要選中,在這裡設定
      if (fetchedOptions.length > 0 && !initialSelectedValue) {
        setSelectedOption(fetchedOptions[0].value); // 假設第一個是預設值
      }
    }

    fetchOptions();
  }, []); // 空依賴陣列確保只在掛載時執行一次

  // 返回用於處理選擇事件的方法以及當前選中的選項值
  return { options, handleSelectChange, selectedOption };
}

// 在元件內部使用該hook
function DropdownComponent() {
  // 使用自定義hook獲取下拉框資料並傳遞初始值
  const { options, handleSelectChange, selectedOption } = useDropdownOptions();

  // 獲取下拉框資料後立即執行的邏輯
  useEffect(() => {
    performCalculation(selectedOption);
    updateFormField(selectedOption);
  }, [selectedOption]); // 當selectedOption改變時重新執行此effect

  // 處理選項變化的事件
  const handleSelection = (event) => {
    handleSelectChange(event.target.value);
  };

  return (
    <select value={selectedOption} onChange={handleSelection}>
      {options.map(option => (
        <option key={option.id} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

// 下拉框選項改變後的操作函式
const performCalculation = (selectedOption) => {
  // 根據selectedOption進行計算...
};

// 更新表單欄位的函式
const updateFormField = (selectedOption) => {
  // 更新表單欄位...
};

這樣,我們仍然可以在useDropdownOptions hook 中獲取並設定下拉框選項,同時在元件內部透過另一個useEffect監聽selectedOption的變化以執行相應的計算和更新操作。

相關文章