React 最佳实践和模式以减少代码 - 第 3 部分

2025-06-08

React 最佳实践和模式以减少代码 - 第 3 部分

React 最佳实践和模式以减少代码

这是关于 React 最佳实践的第三篇文章,如果您还没有阅读我之前的文章,请查看。

React 最佳实践和模式以减少代码 - 第 1 部分
React 最佳实践和模式以减少代码 - 第 2 部分

让我们看一些减少代码的最佳实践和模式。


将令牌存储到 HTTP Cookie 而不是 localStorage
错误代码:
const token = localStorage.getItem("token");
if (token) {
  axios.defaults.headers.common["Authorization"] = token;
}
Enter fullscreen mode Exit fullscreen mode
好的代码:
import Cookies from "js-cookie"; //  use another library if you want

const token = Cookies.get("token");
if (token) {
  axios.defaults.headers.common["Authorization"] = token;
}
Enter fullscreen mode Exit fullscreen mode
更好的代码:
No Code 😉
Enter fullscreen mode Exit fullscreen mode

笔记:

  • Cookie 会与同一域名下的所有网站共享。无需将 token 传递给每个请求。如果后端与前端不在同一个域名下,则必须使用第二种方法。
  • 使用 HttpOnly 属性来阻止通过 JavaScript 访问 cookie 值(令牌)。但您需要在 React 应用程序中使用一些标志来检查路由访问。

使用拦截器获取授权令牌或任何其他常见标头
错误代码:
axios.get("/api", {
  headers: {
    ts: new Date().getTime(),
  },
});
Enter fullscreen mode Exit fullscreen mode
好的代码:
// 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");
Enter fullscreen mode Exit fullscreen mode

使用 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>
);
Enter fullscreen mode Exit fullscreen mode
好的代码:
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
Enter fullscreen mode Exit fullscreen mode

对 styled-components 使用辅助函数
代码还不错,但是当你从 px 的角度思考时,它很难阅读。
const Button = styled.button`
  margin: 1.31rem 1.43rem;
  padding: 1.25rem 1.5rem;
`;
Enter fullscreen mode Exit fullscreen mode
创建辅助函数以将 px 转换为 rem
const toRem = (value) => `${value / 16}rem`;
const Button = styled.button`
  margin: ${toRem(21)} ${toRem(23)};
  padding: ${toRem(20)} ${toRem(24)};
`;
Enter fullscreen mode Exit fullscreen mode

使用通用函数来改变输入数据
错误代码:
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>
);
Enter fullscreen mode Exit fullscreen mode
好的代码:
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>
);
Enter fullscreen mode Exit fullscreen mode

使用交叉观察器进行延迟加载
错误代码:
element.addEventListener("scroll", function (e) {
  // do something
});
Enter fullscreen mode Exit fullscreen mode
好的代码:
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]);

Enter fullscreen mode Exit fullscreen mode

使用 HOC 进行身份验证和私有路由
错误代码:
const Component = () => {
  if (!isAuthenticated()) {
    return <Redirect to="/login" />;
  }
  return <div></div>;
};
Enter fullscreen mode Exit fullscreen mode
好的代码:
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);
Enter fullscreen mode Exit fullscreen mode

使用路由对象数组来定义路由
常见做法:
return (
  <Router>
    <Route path="/" element={<App />} />
    <Route path="/about" element={<About />} />
    <Route path="/topics" element={<Topics />} />
  </Router>
);
Enter fullscreen mode Exit fullscreen mode
好的代码:
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>;
Enter fullscreen mode Exit fullscreen mode

注意:这需要更多代码,但更灵活。如果要使用更多 HOC,只需更新 createRoute 即可。


使用 Typescript
如果你不使用 Typescript 也没什么问题 😀,但它会帮助你编写更好的代码
npx create-react-app my-app --template typescript
Enter fullscreen mode Exit fullscreen mode

使用 eslint、prettier 进行格式化
npm install -D eslint prettier
npx eslint --init
Enter fullscreen mode Exit fullscreen mode
参考: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"
  ]
}
Enter fullscreen mode Exit fullscreen mode

笔记:

  • 您可以更新配置,以便在提交时运行 Prettier 和 eslint。您可以在项目 package.json 中添加或删除命令。
  • 最好为此设置 CI 和 CD,有人可以注释掉预提交钩子并将代码推送到 git。

使用 vscode 扩展进行更好的开发
自动关闭标签自动重命名标签CodeMetricsCSS PeekES7+ React/Redux/React-Native 代码片段EslintGitLens导入成本Prettier

注意:一定要尝试代码复杂度扩展(CodeMetrics)。它能显示代码的复杂度,帮助你编写更好的代码。

React 最佳实践和模式以减少代码 - 第 3 部分


感谢您的阅读😊

有任何问题或其他信息吗?请留言。

如果你还没有读过

关注我

Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon

鏂囩珷鏉ユ簮锛�https://dev.to/devsmitra/react-best-practices-and-patterns-to-reduce-code-part-3-4bh1
PREV
如何让你的 GitHub 个人资料更具吸引力
NEXT
20+ 个实用的 JavaScript 函数,助您简化代码 | JavaScript 教程