iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Modern Web

寫出好維護又簡潔的 react 程式碼 feat: Function Programming系列 第 13

day13: 模組化好的寫法 -單一功能原則(1)

在程式碼中,我們常常因為需要在一個功能當中觸發不同的 side effect,會導致一段 function 中,會參雜其他功能的判斷和觸發,而這些功能到最後越來越龐大時,就會變能難以維護的一段 code,這些觸發和判斷就是 side effect,另外程式碼依賴其他程式碼功能很深時,就叫做高耦合

這邊為了讓每段程式都讓他只做該做的事時,我們就必須遵守單一功能原則,讓每段程式碼只做他該做的事。譬如下面有一段 code,是實踐要個人資料的功能,在打 api 驗證失敗後會觸發 popup,接著按下 popup 上的按鈕會觸發其他事件。

// Profile.jsx
import {useEffect, useCallback ,useState} from 'react';
import loginAPI from './api.js';
import axios from 'axios'; //axios 為前端一套處理 call api 的套件

const Profile = ()=>{
	const [userData,updataUserData] = useState({});
	const [userError,updateUserError] = useState('');

	const fecthUser = useCallback(async(url)=>{
		try{
				const result = await axios.get(url);
				if(result.status === 200 && result.data 
						&& Object.keys(result.data)?.length > 0){
						userData(result.data);
				}else{
						updateUserError(result.error??'');	
		    }
		}catch(err){
				console.log('fetch uset error',err);
		}
	},[userData]);

	useEffect(()=>{
		fecthUser();
	},[]);
	
	return (
			<div>
					{Object.keys(userData).length > 0 &&
					<>
						<div>Name:{userData.name}</div>
						<div>Name:{userData.email}</div>
						<div>Name:{userData.phone}</div>
					</>
					}
					{userError && <div>{userError}</div>}
       </div>)

}

export default Profile;

上面的程式碼我們可以發現,當在 callapi 時,在 fetch login api 後,直接在 fetchUser 的 function 處理 存資料和 errorHandle,這邊會造成各個資料綁在一起,假如 popup 發現不正確,這時候我們就必須要去 fetchUser 找究竟哪個程式碼有錯。

https://ithelp.ithome.com.tw/upload/images/20211002/201073077HiZZf8hK3.png

比較好的方式是我們把整段程式分成幾個部分,讓他們的 function 都做自己的功能

  • fetchUser 取資料
  • updataUserData
  • updateUserError
  • popup 呈現
  • 資料呈現
// fetchUser function 改成 useFetchAPI function

import {useRef, useEffect} from 'react';
import axios from 'axios';

export default useFetchAPI(url,options){
	const [data,setData] = useState(null);
	const [error,setError] = useState(null);
	const urlRef = useRef('');

	if(!url || urlRef.current === url){
		return;
	};

	const callApi = useCallback((url,method = 'get',data:{})=>{
		return axios({
		  method,
		  url,
		  data;
		});
	},[])

	useEffect(()=>{
		callApi(url,options.method,options.data)
			.then((res)=>{
				if(result.status === 200 && result.data 
							&& Object.keys(result.data)?.length > 0){
							userData(result.data);}
			})
			.catch(err=>{
				setError(result.error);
			})
	},[url])
	return {
		data,
		error
	}
		
}

這時候我們可以發現,callapi 只要專注在拿資料的處理
https://ithelp.ithome.com.tw/upload/images/20211002/20107307ls2ORgmfj8.png

而狀態的處理則交給,setData 和 setError,同時 setData 和 setError 不會對 callapi 內部造成影響。


上一篇
day12: 模組化好的寫法-為什麼要模組化
下一篇
day14: 模組化好的寫法 -單一功能原則(2)
系列文
寫出好維護又簡潔的 react 程式碼 feat: Function Programming30

尚未有邦友留言

立即登入留言