日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

教你應(yīng)用?SOLID?原則整理?React?代碼之單一原則_React

作者:桃翁 ? 更新時(shí)間: 2022-09-07 編程語(yǔ)言

SOLID 原則的主要是作為關(guān)心自己工作的軟件專(zhuān)業(yè)人員的指導(dǎo)方針,那些以經(jīng)得起時(shí)間考驗(yàn)的設(shè)計(jì)精美的代碼庫(kù)為榮的人。

今天,我們將從一個(gè)糟糕的代碼示例開(kāi)始,應(yīng)用 SOLID 的第一個(gè)原則,看看它如何幫助我們編寫(xiě)小巧、漂亮、干凈的并明確責(zé)任的 React 組件,。

什么是單一責(zé)任原則?

單一責(zé)任原則告訴我們的是,每個(gè)類(lèi)或組件應(yīng)該有一個(gè)單一的存在目的。

組件應(yīng)該只做一件事,并且做得很好。

讓我們重構(gòu)一段糟糕但正常工作的代碼,并使用這個(gè)原則使其更加清晰和完善。

讓我們從一個(gè)糟糕的例子開(kāi)始

首先讓我們看看一些違反這一原則的代碼,添加注釋是為了更好地理解:

import?React,?{useEffect,?useReducer,?useState}?from?"react";
const?initialState?=?{
????isLoading:?true
};
//?復(fù)雜的狀態(tài)管理
function?reducer(state,?action)?{
????switch?(action.type)?{
????????case?'LOADING':
????????????return?{isLoading:?true};
????????case?'FINISHED':
????????????return?{isLoading:?false};
????????default:
????????????return?state;
????}
}
export?const?SingleResponsibilityPrinciple?=?()?=>?{
????const?[users?,?setUsers]?=?useState([])
????const?[filteredUsers?,?setFilteredUsers]?=?useState([])
????const?[state,?dispatch]?=?useReducer(reducer,?initialState);
????const?showDetails?=?(userId)?=>?{
????????const?user?=?filteredUsers.find(user?=>?user.id===userId);
????????alert(user.contact)
????}
????//?遠(yuǎn)程數(shù)據(jù)獲取
????useEffect(()?=>?{
????????dispatch({type:'LOADING'})
????????fetch('https://jsonplaceholder.typicode.com/users')
????????????.then(response?=>?response.json())
????????????.then(json?=>?{
????????????????dispatch({type:'FINISHED'})
????????????????setUsers(json)
????????????})
????},[])
????//?數(shù)據(jù)處理
????useEffect(()?=>?{
????????const?filteredUsers?=?users.map(user?=>?{
????????????return?{
????????????????id:?user.id,
????????????????name:?user.name,
????????????????contact:?`${user.phone}?,?${user.email}`
????????????};
????????});
????????setFilteredUsers(filteredUsers)
????},[users])
????//?復(fù)雜UI渲染
????return?<>
????????<div>?Users?List</div>
????????<div>?Loading?state:?{state.isLoading??'Loading':?'Success'}</div>
????????{users.map(user?=>?{
????????????return?<div?key={user.id}?onClick={()?=>?showDetails(user.id)}>
????????????????<div>{user.name}</div>
????????????????<div>{user.email}</div>
????????????</div>
????????})}
????</>
}

這段代碼的作用

這是一個(gè)函數(shù)式組件,我們從遠(yuǎn)程數(shù)據(jù)源獲取數(shù)據(jù),再過(guò)濾數(shù)據(jù),然后在 UI 中顯示數(shù)據(jù)。我們還檢測(cè) API 調(diào)用的加載狀態(tài)。

為了更好地理解這個(gè)例子,我把它簡(jiǎn)化了。但是你幾乎可以在任何地方的同一個(gè)組件中找到它們!這里發(fā)生了很多事情:

  • 遠(yuǎn)程數(shù)據(jù)的獲取

  • 數(shù)據(jù)過(guò)濾

  • 復(fù)雜的狀態(tài)管理

  • 復(fù)雜的 UI 功能

因此,讓我們探索如何改進(jìn)代碼的設(shè)計(jì)并使其緊湊。

1. 移動(dòng)數(shù)據(jù)處理邏輯

不要將 HTTP 調(diào)用保留在組件中。這是經(jīng)驗(yàn)之談。您可以采用幾種策略從組件中刪除這些代碼。

您至少應(yīng)該創(chuàng)建一個(gè)自定義 Hook 并將數(shù)據(jù)獲取邏輯移動(dòng)到那里。例如,我們可以創(chuàng)建一個(gè)名為?useGetRemoteData?的 Hook,如下所示:

import?{useEffect,?useReducer,?useState}?from?"react";
const?initialState?=?{
????isLoading:?true
};
function?reducer(state,?action)?{
????switch?(action.type)?{
????????case?'LOADING':
????????????return?{isLoading:?true};
????????case?'FINISHED':
????????????return?{isLoading:?false};
????????default:
????????????return?state;
????}
}
export?const?useGetRemoteData?=?(url)?=>?{
????const?[users?,?setUsers]?=?useState([])
????const?[state,?dispatch]?=?useReducer(reducer,?initialState);
????const?[filteredUsers?,?setFilteredUsers]?=?useState([])
????useEffect(()?=>?{
????????dispatch({type:'LOADING'})
????????fetch('https://jsonplaceholder.typicode.com/users')
????????????.then(response?=>?response.json())
????????????.then(json?=>?{
????????????????dispatch({type:'FINISHED'})
????????????????setUsers(json)
????????????})
????},[])
????useEffect(()?=>?{
????????const?filteredUsers?=?users.map(user?=>?{
????????????return?{
????????????????id:?user.id,
????????????????name:?user.name,
????????????????contact:?`${user.phone}?,?${user.email}`
????????????};
????????});
????????setFilteredUsers(filteredUsers)
????},[users])
????return?{filteredUsers?,?isLoading:?state.isLoading}
}

現(xiàn)在我們的主要組件看起來(lái)像這樣:

import?React?from?"react";
import?{useGetRemoteData}?from?"./useGetRemoteData";

export?const?SingleResponsibilityPrinciple?=?()?=>?{

????const?{filteredUsers?,?isLoading}?=?useGetRemoteData()

????const?showDetails?=?(userId)?=>?{
????????const?user?=?filteredUsers.find(user?=>?user.id===userId);
????????alert(user.contact)
????}

????return?<>
????????<div>?Users?List</div>
????????<div>?Loading?state:?{isLoading??'Loading':?'Success'}</div>
????????{filteredUsers.map(user?=>?{
????????????return?<div?key={user.id}?onClick={()?=>?showDetails(user.id)}>
????????????????<div>{user.name}</div>
????????????????<div>{user.email}</div>
????????????</div>
????????})}
????</>
}

看看我們的組件現(xiàn)在是多么的小,多么的容易理解!這是在錯(cuò)綜復(fù)雜的代碼庫(kù)中所能做的最簡(jiǎn)單、最重要的事情。

但我們可以做得更好。

2. 可重用的數(shù)據(jù)獲取鉤子

現(xiàn)在,當(dāng)我們看到我們?useGetRemoteData?Hook 時(shí),我們看到這個(gè) Hook 正在做兩件事:

  • 從遠(yuǎn)程數(shù)據(jù)源獲取數(shù)據(jù)

  • 過(guò)濾數(shù)據(jù)

讓我們把獲取遠(yuǎn)程數(shù)據(jù)的邏輯提取到一個(gè)單獨(dú)的鉤子,這個(gè)鉤子的名字是?useHttpGetRequest,它把 URL 作為一個(gè)參數(shù):

import?{useEffect,?useReducer,?useState}?from?"react";
import?{loadingReducer}?from?"./LoadingReducer";

const?initialState?=?{
????isLoading:?true
};

export?const?useHttpGetRequest?=?(URL)?=>?{

????const?[users?,?setUsers]?=?useState([])
????const?[state,?dispatch]?=?useReducer(loadingReducer,?initialState);

????useEffect(()?=>?{
????????dispatch({type:'LOADING'})
????????fetch(URL)
????????????.then(response?=>?response.json())
????????????.then(json?=>?{
????????????????dispatch({type:'FINISHED'})
????????????????setUsers(json)
????????????})
????},[])

????return?{users?,?isLoading:?state.isLoading}
}

我們還將 reducer 邏輯移除到一個(gè)單獨(dú)的文件中:

export?function?loadingReducer(state,?action)?{
????switch?(action.type)?{
????????case?'LOADING':
????????????return?{isLoading:?true};
????????case?'FINISHED':
????????????return?{isLoading:?false};
????????default:
????????????return?state;
????}
}

所以現(xiàn)在我們的?useGetRemoteData?變成了:

import?{useEffect,?useState}?from?"react";
import?{useHttpGetRequest}?from?"./useHttpGet";
const?REMOTE_URL?=?'https://jsonplaceholder.typicode.com/users'

export?const?useGetRemoteData?=?()?=>?{
????const?{users?,?isLoading}?=?useHttpGetRequest(REMOTE_URL)
????const?[filteredUsers?,?setFilteredUsers]?=?useState([])

????useEffect(()?=>?{
????????const?filteredUsers?=?users.map(user?=>?{
????????????return?{
????????????????id:?user.id,
????????????????name:?user.name,
????????????????contact:?`${user.phone}?,?${user.email}`
????????????};
????????});
????????setFilteredUsers(filteredUsers)
????},[users])

????return?{filteredUsers?,?isLoading}
}

干凈多了,對(duì)吧? 我們能做得更好嗎? 當(dāng)然,為什么不呢?

3. 分解 UI 組件

看看我們的組件,其中顯示了用戶(hù)的詳細(xì)信息。我們可以為此創(chuàng)建一個(gè)可重用的 UserDetails 組件:

const?UserDetails?=?(user)?=>?{

????const?showDetails?=?(user)?=>?{
????????alert(user.contact)
????}

????return?<div?key={user.id}?onClick={()?=>?showDetails(user)}>
????????<div>{user.name}</div>
????????<div>{user.email}</div>
????</div>
}

最后,我們的原始組件變成:

import?React?from?"react";
import?{useGetRemoteData}?from?"./useGetRemoteData";

export?const?Users?=?()?=>?{
????const?{filteredUsers?,?isLoading}?=?useGetRemoteData()

????return?<>
????????<div>?Users?List</div>
????????<div>?Loading?state:?{isLoading??'Loading':?'Success'}</div>
????????{filteredUsers.map(user?=>?<UserDetails?user={user}/>)}
????</>
}

我們把代碼從 60 行精簡(jiǎn)到了 12 行!我們創(chuàng)建了五個(gè)獨(dú)立的組成部分,每個(gè)部分都有明確而單一的職責(zé)。

讓我們回顧一下我們剛剛做了什么

讓我們回顧一下我們的組件,看看我們是否實(shí)現(xiàn)了 SRP:

  • Users.js?- 負(fù)責(zé)顯示用戶(hù)列表

  • UserDetails.js?ー 負(fù)責(zé)顯示用戶(hù)的詳細(xì)資料

  • useGetRemoteData.js?- 負(fù)責(zé)過(guò)濾遠(yuǎn)程數(shù)據(jù)

  • useHttpGetrequest.js?- 負(fù)責(zé) HTTP 調(diào)用

  • LoadingReducer.js?- 復(fù)雜的狀態(tài)管理

當(dāng)然,我們可以改進(jìn)很多其他的東西,但是這應(yīng)該是一個(gè)很好的起點(diǎn)。

總結(jié)

這是一個(gè)簡(jiǎn)單的演示,演示如何減少每個(gè)文件中的代碼量,并使用 SOLID 的強(qiáng)大功能創(chuàng)建漂亮的可重用組件。

原文鏈接:https://mp.weixin.qq.com/s/oOcoy5rJwqH939MIOrgaiA

欄目分類(lèi)
最近更新