浏览完这篇文章,结合平时开发中遇到的一些问题typescript使用代码,觉得写起来比较实用。 新的一年从翻译这篇文章开始。 自己总结的同时,也方便大家写出更好的代码。 有些地方不仅翻译了,还添加了一些我自己的理解和看法。
前言
干净的代码不是有效的代码。 它指的是代码干净、易于阅读、易于理解、易于维护。
让我们看一下 React 中干净代码的最佳实践。 它使我们编写的代码更易于维护。
1. 为所有值提供显式类型
在使用 TypeScript 时,很多人忽略了给相应的值显式类型。 因此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 = (props) => {
const { name, children, ...rest } = props;
// ...
};
2.在update方法中使用之前的状态
如果更新后的状态依赖于之前的状态,那么建议使用函数形式。 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 (
);
};
正确的例子
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 (
);
};
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 (
{posts.map((post) => (
{post.title}
))}
);
}
正确的例子
// src/App.tsx
export default function App() {
return (
<Navigation title="App" />
);
}
// src/components/Navigation.tsx
interface NavigationProps {
title: string;
}
export default function Navigation({ title }: NavigationProps) {
return (
);
}
// 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 (
{posts.map((post) => (
))}
);
}
// src/components/Post.tsx
interface PostProps {
title: string;
}
export default function Post({ title }: PostProps) {
// 这里只是伪代码。真实的项目中,这里应该还会有很多节点和样式
return {title} ;
}
4.使用enum或const方法配置一个变量的多个值
一个变量可能会取多个不同的值,然后以其他方式对不同的值产生不同的作用。 使用enum或const的方法来配置该值。 如果以后想改的话可以一起改,查找起来会更方便。
错误示例
import React, { useState } from "react";
export const App = () => {
const [status, setStatus] = useState("Pending");
return (
{status}
);
};
正确的例子
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(Status.Pending);
// use values as types (only enum available)
// const [status, setStatus] = useState(Status.Pending);
return (
{status}
);
};
5. 单独定义风暴的方法
为风暴或方法定义单独的函数名称可以更容易地知道我们要做什么。 而如果是组件的反弹方法,使用useCallback封装也会减少组件的重新渲染。
错误示例
const App = () => {
return (
<button
onClick={() => {
// ...
}}
>
Toggle Dark Mode
);
};
正确的例子
const App = () => {
const handleDarkModeToggle = () => {
// ...
};
return (
);
};
6. 优雅地有条件地渲染元素
有条件地渲染节点在 React 中非常常见。 因此,书写形式也需要越来越工整。
错误示例
const App = () => {
const [isTextShown, setIsTextShown] = useState(false);
const handleToggleText = () => {
setIsTextShown((isTextShown) => !isTextShown);
};
return (
{isTextShown ? Now You See Me
: null}
{isTextShown && `isTextShown` is true
}
{!isTextShown && `isTextShown` is false
}
);
};
正确的例子
const App = () => {
const [isTextShown, setIsTextShown] = useState(false);
const handleToggleText = () => {
setIsTextShown((isTextShown) => !isTextShown);
};
return (
{isTextShown && Now You See Me
}
{isTextShown ? (
`isTextShown` is true
) : (
`isTextShown` is false
)}
);
};
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 ;
};
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" />;
};
未定义类型的 Props 值
就像 TypeScript 或 javaScript 的基本类型一样。 如果一个 prop 没有被写入,它的值是未定义的。
错误示例
interface AvatarProps {
username?: string;
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return ;
};
正确的例子
interface AvatarProps {
username?: string;
// OR `username: string | undefined`
}
const Avatar = ({ username }: AvatarProps) => {
// ...
};
const Profile = () => {
return ;
};
原文发布于微信公众号(前端学习总结):让React + Typescript代码更干净的七种方法