您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“如何應用SOLID原則”,內容詳細,步驟清晰,細節處理妥當,希望這篇“如何應用SOLID原則”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
單一責任原則告訴我們的是,每個類或組件應該有一個單一的存在目的。
組件應該只做一件事,并且做得很好。
讓我們重構一段糟糕但正常工作的代碼,并使用這個原則使其更加清晰和完善。
首先讓我們看看一些違反這一原則的代碼,添加注釋是為了更好地理解:
import React, {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 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) } // 遠程數據獲取 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]) // 復雜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> })} </> }
這段代碼的作用
這是一個函數式組件,我們從遠程數據源獲取數據,再過濾數據,然后在 UI 中顯示數據。我們還檢測 API 調用的加載狀態。
為了更好地理解這個例子,我把它簡化了。但是你幾乎可以在任何地方的同一個組件中找到它們!這里發生了很多事情:
遠程數據的獲取
數據過濾
復雜的狀態管理
復雜的 UI 功能
因此,讓我們探索如何改進代碼的設計并使其緊湊。
不要將 HTTP 調用保留在組件中。這是經驗之談。您可以采用幾種策略從組件中刪除這些代碼。
您至少應該創建一個自定義 Hook 并將數據獲取邏輯移動到那里。例如,我們可以創建一個名為 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} }
現在我們的主要組件看起來像這樣:
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> })} </> }
看看我們的組件現在是多么的小,多么的容易理解!這是在錯綜復雜的代碼庫中所能做的最簡單、最重要的事情。
但我們可以做得更好。
現在,當我們看到我們 useGetRemoteData
Hook 時,我們看到這個 Hook 正在做兩件事:
從遠程數據源獲取數據
過濾數據
讓我們把獲取遠程數據的邏輯提取到一個單獨的鉤子,這個鉤子的名字是 useHttpGetRequest
,它把 URL 作為一個參數:
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 邏輯移除到一個單獨的文件中:
export function loadingReducer(state, action) { switch (action.type) { case 'LOADING': return {isLoading: true}; case 'FINISHED': return {isLoading: false}; default: return state; } }
所以現在我們的 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} }
干凈多了,對吧? 我們能做得更好嗎? 當然,為什么不呢?
看看我們的組件,其中顯示了用戶的詳細信息。我們可以為此創建一個可重用的 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 行精簡到了 12 行!我們創建了五個獨立的組成部分,每個部分都有明確而單一的職責。
讓我們回顧一下我們的組件,看看我們是否實現了 SRP:
Users.js
- 負責顯示用戶列表
UserDetails.js
ー 負責顯示用戶的詳細資料
useGetRemoteData.js
- 負責過濾遠程數據
useHttpGetrequest.js
- 負責 HTTP 調用
LoadingReducer.js
- 復雜的狀態管理
當然,我們可以改進很多其他的東西,但是這應該是一個很好的起點。
讀到這里,這篇“如何應用SOLID原則”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。