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 内部造成影响。


<<:  【Day 13】- 用 JSON 储存爬来的 PTT 文章。(实战 PTT 爬虫 3/3)

>>:  Day13-290. Word Pattern

[DAY 23] _I2S协议(1)

昨天介绍完I2S由於我还没写出stm32f030的spi读写Flash的程序,就没付上代码解释了,我...

【Day 04】String Methods

前言 今天要来介绍 string Methods,可以把 string 进行各种处理,来做出你想做的...

Day29 Gin with Async

前情提要 由於在POST /v1/users/ 时我们会需要透过smtp寄出通知信再回respons...

[Golang] Pointer

Go provide pointer similar to C and C++. Go use &a...

30天轻松学会unity自制游戏-制作BOSS

先把BOSS放在游戏场景的最後面,跟Player一样把3个Boss0~2放到场景上,存一个Boss待...