一個元件應該只有一個改變的理由,這意味著它應該只有一項工作。
應該這樣:
// 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>
);
};
軟體實體應該對擴充開放,但對修改關閉。
應該這樣:
// 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>
);
};
超類別的物件可以用其子類別的物件替換,而不會破壞應用程式。
應該這樣:
// 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>
);
};
任何客戶端都不應該被迫依賴它不使用的方法。
應該這樣:
// 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>;
};
高層模組不應該依賴低層模組。兩者都應該依賴抽象。
應該這樣:
和狀態管理。
// 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