浏览到这篇文章,再结合着平时开发时遇见的一些问题,觉得写得比较实用。新的一年,就从翻译这篇文章开始。自己总结的同时也方便大家写出更好的代码。部分地方除了翻译外,还加上了些自己的理解与想法。
https://dev.to/ruppysuppy/7-tips-for-clean-react-typescript-code-you-must-know-2da2
前言
干净的代码并不是指能运行的代码。它指的是 代码整洁
、容易阅读
、方便理解
以及 易于维护
。
让我们来看一下 React
整洁代码的最佳实践。它能让我们写的代码维护起来更加容易。
1. 为所有的值提供显式类型
在使用 TypeScript
时,很多人都忽略了给对应的值显式类型。也因此 Get
不到 TypeScript
真正带来的好处。比如在组件中写这样的代码:
错误示例1
const Component = ({ children }: any) => {
// ...
};
错误示例2
const Component = ({ children }: object) => {
// ...
};
相反,使用正确的类型定义,能让我们使用起来更轻松,编辑器也会给我们更多的提示。
正确示例
import { FC, ReactNode } from "react";
interface ComponentProps {
children: ReactNode;
name: string;
}
const Component:FC<ComponentProps> = (props) => {
const { name, children, ...rest } = props;
// ...
};
2. 在更新的方法中使用之前的 state
如果更新的状态要依赖于前一个 State
,那么推荐使用函数的方式。React
的更新的批处理的,不以这种方式可能会导致意想不到的结果。
错误示例
import React, { useState } from "react";
export const App = () => {
const [isDisabled, setIsDisabled] = useState(false);
const toggleButton = () => {
setIsDisabled(!isDisabled);
};
// here toggling twice will yeild the same result as toggling once
const toggleButtonTwice = () => {
toggleButton();
toggleButton();
};
return (
<div>
<button disabled={isDisabled}>
I'm {isDisabled ? "disabled" : "enabled"}
</button>
<button onClick={toggleButton}>
Toggle button state
</button>
<button onClick={toggleButtonTwice}>
Toggle button state 2 times
</button>
</div>
);
};
正确示例
import React, { useState } from "react";
export const App = () => {
const [isDisabled, setIsDisabled] = useState(false);
const toggleButton = () => {
// 使用函数的方式。这里如果使用了 useCallback,也不用将 isDisabled 作为依赖传入
setIsDisabled((isDisabled) => !isDisabled);
};
const toggleButtonTwice = () => {
toggleButton();
toggleButton();
};
return (
<div>
<button disabled={isDisabled}>
I'm {isDisabled ? "disabled" : "enabled"}
</button>
<button onClick={toggleButton}>
Toggle button state
</button>
<button onClick={toggleButtonTwice}>
Toggle button state 2 times
</button>
</div>
);
};
3. 让单个文件更加干净整洁
将一个页面的不同内容提取为不同的组件。保持文件的原子性和精简性,可以使调试、维护甚至查找文件变得更加容易。
错误示例
// src/App.tsx
export default function App() {
const posts = [
{
id: 1,
title: "How to write clean react code",
},
{
id: 2,
title: "Eat, sleep, code, repeat",
},
];
return (
<main>
<nav>
<h1>App</h1>
</nav>
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.title}
</li>
))}
</ul>
</main>
);
}
正确示例
// src/App.tsx
export default function App() {
return (
<main>
<Navigation title="App" />
<Posts />
</main>
);
}
// src/components/Navigation.tsx
interface NavigationProps {
title: string;
}
export default function Navigation({ title }: NavigationProps) {
return (
<nav>
<h1>{title}</h1>
</nav>
);
}
// src/components/Posts.tsx
export default function Posts() {
const posts = [
{
id: 1,
title: "How to write clean react code",
},
{
id: 2,
title: "Eat, sleep, code, repeat",
},
];
return (
<ul>
{posts.map((post) => (
<Post key={post.id} title={post.title} />
))}
</ul>
);
}
// src/components/Post.tsx
interface PostProps {
title: string;
}
export default function Post({ title }: PostProps) {
// 这里只是伪代码。真实的项目中,这里应该还会有很多节点和样式
return <li>{title}</li>;
}
4. 使用 enum 或者 const 的方式来配置一个变量的多个值
一个变量可能会使用多个不同的值,然后在其它方法中根据不同的值做不同的操作。将这些值使用 enum
或者 const
的方式来配置。后面如果要修改,可以统一修改,并且查找起来也会更加方便。
错误示例
import React, { useState } from "react";
export const App = () => {
const [status, setStatus] = useState("Pending");
return (
<div>
<p>{status}</p>
<button onClick={() => setStatus("Pending")}>
Pending
</button>
<button onClick={() => setStatus("Success")}>
Success
</button>
<button onClick={() => setStatus("Error")}>
Error
</button>
</div>
);
};
正确示例
import React, { useState } from "react";
enum Status {
Pending = "Pending",
Success = "Success",
Error = "Error",
}
// 或者
// const Status = {
// Pending: "Pending",
// Success: "Success",
// Error: "Error",
// } as const;
export const App = () => {
// use keys as types (both enum and const available)
const [status, setStatus] = useState<keyof typeof Status>(Status.Pending);
// use values as types (only enum available)
// const [status, setStatus] = useState<typeof Status[keyof typeof Status]>(Status.Pending);
return (
<div>
<p>{status}</p>
<button onClick={() => setStatus(Status.Pending)}>
Pending
</button>
<button onClick={() => setStatus(Status.Success)}>
Success
</button>
<button onClick={() => setStatus(Status.Error)}>
Error
</button>
</div>
);
};
5. 单独定义事件的方法
给一个事件或者方法定义一个单独的函数名,可以更加方便地知道我们要做什么事。并且如果是一个组件的回调方法,使用 useCallback
包裹也会减少组件的 rerender
。
错误示例
const App = () => {
return (
<div>
<button
onClick={() => {
// ...
}}
>
Toggle Dark Mode
</button>
</div>
);
};
正确示例
const App = () => {
const handleDarkModeToggle = () => {
// ...
};
return (
<div>
<button onClick={handleDarkModeToggle}>
Toggle Dark Mode
</button>
</div>
);
};
6. 优雅地有条件渲染元素
在 React
中,根据条件来渲染节点非常常见。因此,使用更加整洁的方式来写也非常必要。
错误示例
const App = () => {
const [isTextShown, setIsTextShown] = useState(false);
const handleToggleText = () => {
setIsTextShown((isTextShown) => !isTextShown);
};
return (
<div>
{isTextShown ? <p>Now You See Me</p> : null}
{isTextShown && <p>`isTextShown` is true</p>}
{!isTextShown && <p>`isTextShown` is false</p>}
<button onClick={handleToggleText}>Toggle</button>
</div>
);
};
正确示例
const App = () => {
const [isTextShown, setIsTextShown] = useState(false);
const handleToggleText = () => {
setIsTextShown((isTextShown) => !isTextShown);
};
return (
<div>
{isTextShown && <p>Now You See Me</p>}
{isTextShown ? (
<p>`isTextShown` is true</p>
) : (
<p>`isTextShown` is false</p>
)}
<button onClick={handleToggleText}>Toggle</button>
</div>
);
};
7. 使用 JSX 简写
Boolean 类型的 Props 值
如果一个 组件的 Props
的值为 true
,那么可以省略 ={true}
。
错误示例
interface TextFieldProps {
fullWidth: boolean;
}
const TextField = ({ fullWidth }: TextFieldProps) => {
// ...
};
const App = () => {
return <TextField fullWidth={true} />;
};
正确示例
interface TextFieldProps {
fullWidth: boolean;
}
const TextField = ({ fullWidth }: TextFieldProps) => {
// ...
};
const App = () => {
return <TextField fullWidth />;
};
String 类型的 Props 值
String
类型的值可以直接使用单引号或者双引号括起来就行,不用再用花括号包裹。花括号是用来包裹变量的。
错误示例
interface AvatarProps {
username: string;
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return <Avatar username={"John Wick"} />;
};
正确示例
interface AvatarProps {
username: string;
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return <Avatar username="John Wick" />;
};
Undefined 类型的 Props 值
就像 TypeScript
或者 JavaScript
的基础类型一样。如果一个 prop
没有写,那么它的值就是 undefined
。
错误示例
interface AvatarProps {
username?: string;
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return <Avatar username={undefined} />;
};
正确示例
interface AvatarProps {
username?: string;
// OR `username: string | undefined`
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return <Avatar />;
};
原文始发于微信公众号(前端学习总结):让 React + Typescript 代码更整洁的七个技巧
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/83080.html