單一職責原則(SRP)

一個元件應該只有一個改變的理由,這意味著它應該只有一項工作。

範例:使用者設定檔元件

應該這樣:

  • 將職責分解為更小的功能元件。
// UserProfile.js
const UserProfile = ({ user }) => {
  return (
    <div>
      <UserAvatar user={user} />
      <UserInfo user={user} />
    </div>
  );
};

// UserAvatar.js
const UserAvatar = ({ user }) => {
  return <img src={user.avatarUrl} alt={`${user.name}'s avatar`} />;
};

// UserInfo.js
const UserInfo = ({ user }) => {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
    </div>
  );
};

不要這樣:

  • 將顯示、資料取得和業務邏輯組合在一個元件中。
// IncorrectUserProfile.js
const IncorrectUserProfile = ({ user }) => {
  // Fetching data, handling business logic and displaying all in one
  const handleEdit = () => {
    console.log("Edit user");
  };

  return (
    <div>
      <img src={user.avatarUrl} alt={`${user.name}'s avatar`} />
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
      <button onClick={handleEdit}>Edit User</button>
    </div>
  );
};

開閉原理 (OCP)

軟體實體應該對擴充開放,但對修改關閉。

範例:主題按鈕

應該這樣:

  • 使用 props 來擴充元件功能,而無需修改原始元件。
// Button.js
const Button = ({ onClick, children, style }) => {
  return (
    <button onClick={onClick} style={style}>
      {children}
    </button>
  );
};

// Usage
const PrimaryButton = (props) => {
  const primaryStyle = { backgroundColor: 'blue', color: 'white' };
  return <Button {...props} style={primaryStyle} />;
};

不要這樣:

  • 修改原有元件程式碼,直接加入新的樣式或行為。
// IncorrectButton.js
// Modifying the original Button component directly for a specific style
const Button = ({ onClick, children, primary }) => {
  const style = primary ? { backgroundColor: 'blue', color: 'white' } : null;
  return (
    <button onClick={onClick} style={style}>
      {children}
    </button>
  );
};

里氏替換原理 (LSP)

超類別的物件可以用其子類別的物件替換,而不會破壞應用程式。

範例:基本按鈕和圖示按鈕

應該這樣:

  • 確保子類元件可以無縫替換超類元件。
// BasicButton.js
const BasicButton = ({ onClick, children }) => {
  return <button onClick={onClick}>{children}</button>;
};

// IconButton.js
const IconButton = ({ onClick, icon, children }) => {
  return (
    <button onClick={onClick}>
      <img src={icon} alt="icon" />
      {children}
    </button>
  );
};

不要這樣:

  • 引入特定於子類別的屬性,這些屬性在替換時會破壞功能。
// IncorrectIconButton.js
// This button expects an icon and does not handle the absence of one, breaking when used as a BasicButton
const IncorrectIconButton = ({ onClick, icon }) => {
  if (!icon) {
    throw new Error("Icon is required");
  }
  return (
    <button onClick={onClick}>
      <img src={icon} alt="icon" />
    </button>
  );
};

介面隔離原則(ISP)

任何客戶端都不應該被迫依賴它不使用的方法。

範例:文字元件

應該這樣:

  • 針對不同的用途提供特定的介面。
// Text.js
const Text = ({ type, children }) => {
  switch (type) {
    case 'header':
      return <h1>{children}</h1>;
    case 'title':
      return <h2>{children}</h2>;
    default:
      return <p>{children}</p>;
  }
};

不要這樣:

  • 用不必要的屬性使元件變得混亂。
// IncorrectText.js
// This component expects multiple unrelated props, cluttering the interface
const IncorrectText = ({ type, children, onClick, isLoggedIn }) => {
  if (isLoggedIn && onClick) {
    return <a href="#" onClick={onClick}>{children}</a>;
  }
  return type === 'header' ? <h1>{children}</h1> : <p>{children}</p>;
};

依賴倒置原則(DIP)

高層模組不應該依賴低層模組。兩者都應該依賴抽象。

範例:資料獲取

應該這樣:

  • 使用鉤子或類似的模式來抽象資料獲取

和狀態管理。

// useUserData.js (Abstraction)
const useUserData = (userId) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchData(userId).then(setUser);
  }, [userId]);

  return user;
};

// UserProfile.js
const UserProfile = ({ userId }) => {
  const user = useUserData(userId);

  if (!user) return <p>Loading...</p>;
  return <div><h1>{user.name}</h1></div>;
};

不要這樣:

  • 在元件內部硬編碼資料取得。
// IncorrectUserProfile.js
const IncorrectUserProfile = ({ userId }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Fetching data directly inside the component
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(setUser);
  }, [userId]);

  if (!user) return <p>Loading...</p>;
  return <div><h1>{user.name}</h1></div>;
};

原文出處:https://dev.to/drruvari/mastering-solid-principles-in-react-easy-examples-and-best-practices-142b


共有 0 則留言