Best Approaches and Solutions for React Code Minification. Part 3
Hey! This is the third and final part of the series “Best Approaches and Solutions for Minifying React Code” by Rahul Sharma. Previous articles can be found at the links below:
Store the token in cookies instead of localStorage
Bad code:
const token = localStorage.getItem("token");
if (token) {
axios.defaults.headers.common["Authorization"] = token;
}
Good code:
import Cookies from "js-cookie"; // Вы можете использовать другую библиотеку
const token = Cookies.get("token");
if (token) {
axios.defaults.headers.common["Authorization"] = token;
}
Best Code:
Без кода 😉
Note:
Cookies are distributed to all sites within the same domain. So there is no need to prescribe a token in every request. If the backend is not on the same domain as the frontend, then you need to use the solution from the next paragraph.
Use the HttpOnly attribute to avoid accessing cookies through JavaScript.
Use request interceptors for the authorization token or other standard headers
Bad code:
axios.get("/api", {
headers: {
ts: new Date().getTime(),
},
});
Good code:
axios.interceptors.request.use(
(config) => {
// Код, необходимый до отправки запроса
config.headers["ts"] = new Date().getTime();
return config;
},
(error) => {
// Обработка ошибки из запроса
return Promise.reject(error);
}
);
// Компонент
axios.get("/api");
Use react context/redux to pass props to child elements
Bad code:
const auth = { name: "John", age: 30 };
return (
<Router>
<Route path="/" element={<App auth={auth} />} />
<Route path="/home" element={<Home auth={auth} />} />
</Router>
);
Good code:
return (
<Provider store={store}>
<Router>
<Route
path="/"
element={<App />}
/>
<Route
path="/home"
element={<Home />}
/>
</Router>
);
// Внутри дочернего компонента
const { auth } = useContext(AuthContext); // При использовании контекста
const { auth } = useSelector((state) => state.auth); // При использовании redux
Use helper functions for styled-components
Not bad code, but hard to read as everyone is used to thinking in pixels
const Button = styled.button`
margin: 1.31rem 1.43rem;
padding: 1.25rem 1.5rem;
`;
Create a helper function to convert pixels to rem
const toRem = (value) => `${value / 16}rem`;
const Button = styled.button`
margin: ${toRem(21)} ${toRem(23)};
padding: ${toRem(20)} ${toRem(24)};
`;
Use generic functions to change data inside input fields
Bad code:
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>
);
Good code:
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>
);
Use intersection observer to implement lazy loading
Bad code:
element.addEventListener("scroll", function (e) {
// do something
});
Good code:
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;
};
// Компонент
const ref = useRef<any>();
const isIntersecting = useScroll(ref?.current);
useEffect(() => {
if (isIntersecting) {
// вызов API
}
}, [isIntersecting]);
Use HOC for authorization and private navigation
Bad code:
const Component = () => {
if (!isAuthenticated()) {
return <Redirect to="/login" />;
}
return <div></div>;
};
Good code:
const withAuth = (Component) => {
return (props) => {
if (!isAuthenticated()) {
return <Redirect to="/login" />;
}
return <Component {...props} />;
};
};
// Навигация
<Route path="/home" component={withAuth(Home)} />;
// Компонент
const Component = (props) => <div></div>;
export default withAuth(Component);
Use an array with navigation data objects when creating it
Standard Solution:
return (
<Router>
<Route path="/" element={<App />} />
<Route path="/about" element={<About />} />
<Route path="/topics" element={<Topics />} />
</Router>
);
Good code:
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>;
Note: it requires more code but becomes more customizable. For example, if you want to use more HOCs, all you need to do is update createRoute.
Use Typescript
Nothing wrong if you don’t use Typescript 😀try it will help make your code better.
npx create-react-app my-app --template typescript
Use eslint, prettier for formatting
npm install -D eslint prettier
npx eslint --init
Links for setup help: Eslint, Prettier
Use pre-commit hook to start eslint and prettier
Bad code:
npx mrm@2 lint-staged // Установка и конфигурация pre-commit хука
// Скрипт будет создан в корне вашего проекта
.husky/pre-commit
// Package.json
"lint-staged": {
"src/**/*.{js,ts,jsx,tsx}": [
"npm run lint",
"npm run prettier",
"npm run unit-test",
"git add"
]
}
Note:
You can update the config to run prettier and eslint on commit. You can also add or remove commands in package.json.
It’s better if the project has CI & CD set up for this. Someone can comment out the pre-commit hook and push it to git.
Several VSCode extensions for easier development
Auto Close Tag, Auto Rename Tag, CodeMetrics, CSS Peek, ES7+ React/Redux/React-Native snippets, Eslint, GitLens, import cost, Prettier
Note: try extensions for feature complexity estimation (CodeMetrics). This will help in writing better code, as you will see the complexity of executing the code.

Thanks for reading 😊