React 最佳实践和模式以减少代码 - 第 3 部分
这是关于 React 最佳实践的第三篇文章,如果您还没有阅读我之前的文章,请查看。
React 最佳实践和模式以减少代码 - 第 1 部分
React 最佳实践和模式以减少代码 - 第 2 部分
让我们看一些减少代码的最佳实践和模式。
将令牌存储到 HTTP Cookie 而不是 localStorage
错误代码:
const token = localStorage.getItem("token");
if (token) {
axios.defaults.headers.common["Authorization"] = token;
}
好的代码:
import Cookies from "js-cookie"; // use another library if you want
const token = Cookies.get("token");
if (token) {
axios.defaults.headers.common["Authorization"] = token;
}
更好的代码:
No Code 😉
笔记:
- Cookie 会与同一域名下的所有网站共享。无需将 token 传递给每个请求。如果后端与前端不在同一个域名下,则必须使用第二种方法。
- 使用 HttpOnly 属性来阻止通过 JavaScript 访问 cookie 值(令牌)。但您需要在 React 应用程序中使用一些标志来检查路由访问。
使用拦截器获取授权令牌或任何其他常见标头
错误代码:
axios.get("/api", {
headers: {
ts: new Date().getTime(),
},
});
好的代码:
// only once
axios.interceptors.request.use(
(config) => {
// Do something before request is sent
config.headers["ts"] = new Date().getTime();
return config;
},
(error) => {
// Do something with request error
return Promise.reject(error);
}
);
// Component
axios.get("/api");
使用 context/redux 将 props 传递给子项
错误代码:
const auth = { name: "John", age: 30 };
return (
<Router>
<Route path="/" element={<App auth={auth} />} />
<Route path="/home" element={<Home auth={auth} />} />
</Router>
);
好的代码:
return (
<Provider store={store}>
<Router>
<Route
path="/"
element={<App />}
/>
<Route
path="/home"
element={<Home />}
/>
</Router>
);
// Inside child component
const { auth } = useContext(AuthContext); // For context
const { auth } = useSelector((state) => state.auth); // For redux
对 styled-components 使用辅助函数
代码还不错,但是当你从 px 的角度思考时,它很难阅读。
const Button = styled.button`
margin: 1.31rem 1.43rem;
padding: 1.25rem 1.5rem;
`;
创建辅助函数以将 px 转换为 rem
const toRem = (value) => `${value / 16}rem`;
const Button = styled.button`
margin: ${toRem(21)} ${toRem(23)};
padding: ${toRem(20)} ${toRem(24)};
`;
使用通用函数来改变输入数据
错误代码:
const onNameChange = (e) => setName(e.target.value);
const onEmailChange = (e) => setEmail(e.target.value);
return (
<form>
<input type="text" name="name" onChange={onNameChange} />
<input type="text" name="email" onChange={onEmailChange} />
</form>
);
好的代码:
const onInputChange = (e) => {
const { name, value } = e.target;
setFormData((prevState) => ({
...prevState,
[name]: value,
}));
};
return (
<form>
<input type="text" name="name" onChange={onInputChange} />
<input type="text" name="email" onChange={onInputChange} />
</form>
);
使用交叉观察器进行延迟加载
错误代码:
element.addEventListener("scroll", function (e) {
// do something
});
好的代码:
const useScroll = (ele, options = {}): boolean => {
const [isIntersecting, setIsIntersecting] = useState(false);
useEffect(() => {
const cb = (entry) => setIsIntersecting(() => entry.isIntersecting);
const callback: IntersectionObserverCallback = (entries) => entries.forEach(cb);
const observer = new IntersectionObserver(callback, options);
if (ele) observer.observe(ele);
return (): void => ele && observer.unobserve(ele);
}, [ele]);
return isIntersecting;
};
// Component
const ref = useRef<any>();
const isIntersecting = useScroll(ref?.current);
useEffect(() => {
if (isIntersecting) {
// call an API
}
}, [isIntersecting]);
使用 HOC 进行身份验证和私有路由
错误代码:
const Component = () => {
if (!isAuthenticated()) {
return <Redirect to="/login" />;
}
return <div></div>;
};
好的代码:
const withAuth = (Component) => {
return (props) => {
if (!isAuthenticated()) {
return <Redirect to="/login" />;
}
return <Component {...props} />;
};
};
// Route
<Route path="/home" component={withAuth(Home)} />;
// Component
const Component = (props) => <div></div>;
export default withAuth(Component);
使用路由对象数组来定义路由
常见做法:
return (
<Router>
<Route path="/" element={<App />} />
<Route path="/about" element={<About />} />
<Route path="/topics" element={<Topics />} />
</Router>
);
好的代码:
const routes = [
{
path: "/",
role: ["ADMIN"],
element: React.lazy(() => import("../pages/App")),
children: [
{
path: "/child",
element: React.lazy(() => import("../pages/Child")),
},
],
},
{
path: "/about",
role: [],
element: React.lazy(() => import("../pages/About")),
},
{
path: "/topics",
role: ["User"],
element: React.lazy(() => import("../pages/Topics")),
},
];
const createRoute = ({ element, children, role, ...route }) => {
const Component = role.length > 0 ? withAuth(element) : element;
return (
<Route key={route.path} {...route} element={<Component />}>
{children && children.map(createRoute)}
</Route>
);
};
return <Routes>{routes.map(createRoute)}</Routes>;
注意:这需要更多代码,但更灵活。如果要使用更多 HOC,只需更新 createRoute 即可。
使用 Typescript
如果你不使用 Typescript 也没什么问题 😀,但它会帮助你编写更好的代码
npx create-react-app my-app --template typescript
使用 eslint、prettier 进行格式化
npm install -D eslint prettier
npx eslint --init
参考:Eslint 设置,Prettier 设置
😥 我没有添加完整的步骤,我想尽量简洁。如果您遇到任何困难,请留言。
使用 pre-commit hook 运行 eslint 和 prettier
npx mrm@2 lint-staged // This will install and configure pre-commit hook
// This script will be created at the root of your project
.husky/pre-commit
// Package.json
"lint-staged": {
"src/**/*.{js,ts,jsx,tsx}": [
"npm run lint",
"npm run prettier",
"npm run unit-test",
"git add"
]
}
笔记:
- 您可以更新配置,以便在提交时运行 Prettier 和 eslint。您可以在项目 package.json 中添加或删除命令。
- 最好为此设置 CI 和 CD,有人可以注释掉预提交钩子并将代码推送到 git。
使用 vscode 扩展进行更好的开发
自动关闭标签、自动重命名标签、CodeMetrics、CSS Peek、ES7+ React/Redux/React-Native 代码片段、Eslint、GitLens、导入成本、Prettier
注意:一定要尝试代码复杂度扩展(CodeMetrics)。它能显示代码的复杂度,帮助你编写更好的代码。
感谢您的阅读😊
有任何问题或其他信息吗?请留言。
如果你还没有读过

如何使用 AbortController 取消 Javascript API 请求
Rahul Sharma ・ 2022年4月9日
#javascript #webdev #frontend #html
关注我
Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon
鏂囩珷鏉ユ簮锛�https://dev.to/devsmitra/react-best-practices-and-patterns-to-reduce-code-part-3-4bh1