Best Practices for Writing Clean React Code with Examples
React Naming Conventions:
Component Naming Conventions:
- Use PascalCase for react component names, Interfaces & Types:
const ColumnSelectorPropsType = { heading: string };
const ColumnSelector = ({ heading }: ColumnSelectorPropsType) => {
return <div className="column-selector">{heading}</div>;
};
Only one component per file
Use component name for filename
Use .tsx extension for the component file.
All files related to a component must be inside the component folder
ColumnSelector.tsx
- Use camelCase for component instances/Javascript objects/non-component.
const FileUploader = <FileUploader file={} setFile={}/>
- Use component name associated style (.css/.scss/**.js) file name should be in Pascal Case. If there is more than one component ( sub-component ) then it is better to create style folder then add all styled component.
- Add Import React statement in every react component file in single quote.
import React from 'react';
Property/Attribute Naming Conventions:
- Use camelCase for property/attribute names
<workbench exceptionType="UOM" refreshInterval={3000}/>
- Use double quotes for JSX/TSX attributes, use single quotes for js strings.
const exceptionType = 'VPXD';
<ColumnSelector heading="Select Columns" exceptionType={exceptionType}/>
- If the value of the component property is 'true' you don't need to mention it.
const File = ({showFile:boolean, salesId: number}) => {
const filePath = `.../file/${salesId}`;
return (<div className="user"> salesId:{salesId} <a href={fileP/>{filePath}</a> </div>);
<File salesid="12345" showFile={true}/>
//change it to
<File salesid="12345" showFile/>
- Always use propsWithChildren when you pass children to a component
import React, {propsWithChildren} from 'React';
type ComponentProps = {name:string};
const Component=(props:PropsWithChildren<ComponentProps>)=>{...};
Anything to be added in future.
Folder Naming Conventions:
User camelCase for folder names
Use index.js in every folder and export all modules from that folder. This way we can directly import modules from the folder without the complete path.
//folder structure
ColumnSelector - ColumnSelector.tsx
- ColumnSelectro.scss/ColumnSelectro.css
- index.tsx
index.js
export * from './ColumnSelector';
- Folder which having component should follow naming convention as camel case.
Custom Hooks Naming Conventions:
Create custom hooks in separate files inside hooks folder.
Custom hook should start with the string "use". e.g useChangeLog
Component Development Guidelines:
- Separate large inline function from the JSX/TSX:
const Button = () => <button onClick={(event:any)=> console.log(event)} value="Save"/>
//Change to below:
const Button = () => {
const onClick = (event:any)=> console.log(event);
return (<button onClick={onClick} value="Save"/>);
}
- Avoid using indexes as key props to re-render components, instead use unique keys generated by API response.
const list = (<ul>{storeList.map((store,idx,storeList)=>(<li key={idx}>{store.value}</li>))}</ul>);
//change to:
const list = (<ul>{storeList.map((store,idx,storeList)=>(<li key={store.id}>{store.value}</li>))}</ul>);
Group the state variables into a single state whenever possible
const [fileName, setFileName] = useState("");
const [fileState, setFileState] = useState("");
//change it to:
const [file, setFile] = useState({fileName:"", fileState:""});
Avoid Inline styles, use CSS style based components.
Avoid long list of arguments for functions, use objects instead
const getBottomRight = (top:number, left:number, width:number, height:number) => {
return { left: left+width, top: top+height };
}
//change to
const getBottomRight = ( {top, left, width, height} : any) => {
return { left: left+width, top:top+height };
}
- Use template literals instead of string concatenations
const SalesId = 3089089;
const isZipFile = true;
const API = "/switch-user?salesID="+SalesId+"&isZipFile="+ isZipFile;
//change it to
const API = `/switch-user?salesID=${SalesId}&isZipFile=${isZipFile}`;
- Ensure to remove non-html attributes before applying to the jsx.
const saveBtn = ({hide,...rest}:any) => {
return <button {...rest} style={visibility:hide}/>;
}saveBtn({value:"save", onClick:()=>{}, hide});
- Use closing tags for components when there are no children
<FileUploader></FileUploader>
//change it to
<FileUploader/>
- Keep imports in a consistent order
Frame work imports: import React from 'react'
External Library imports: import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
Internal Library imports: import { Loader } from '@replenishments/react-components';
project imports: import useChangeLog from '../hooks/useChangeLog';
- Use Object De-structuring
const Profile = (user:any) => (<div className='user-info'> {profile.salesId}|{profile.name}|{profile.profileType} </div>);
//change it to
const {salesId, name, profileType} = profile;
const Profile = (user:any) => (<div> {salesId}|{name}|{profileType} </div>);
Use functional components instead of class-based components
Try to segregate API call related logic from actual Component.
You can create simple js or ts file and have API call level logic into that file as a function. And whenever you needed import and use this will help to write unit test case.
Any utility function should not be the part of Component container. Please write outside the container.
When you passing props from parent to child please define interface in child component.
If possible, move data fetching logic into container components for clean code
const UserList = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("../users")
.then((res) => res.json())
.then(({ users }) => setUsers(users));
}, []);
return (
<div className='user-list'>
<ul>
{users.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
//Change it to
const useFetchUsers = (setUsers: any) => {
useEffect(() => {
fetch("../users")
.then((res) => res.json())
.then(({ users }) => setUsers(users));
}, [setUsers]);
};
const UserListContainer = () => {
const [users, setUsers] = useState([]);
useFetchUsers(setUsers);
return <UserListPresentation userList={users} />;
};
const UserListPresentation = ({ userList }: { userList: any[] }) => {
return (
<div className='user-list'>
<ul>
{userList.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
Use Proptypes for properties and define types for each property
Define default values for properties
Avoid prop-drilling & prop-polyadic, use redux or context API, and spread props as needed.
Use refs only when needed
Use React.memo() for memoizing components for performance optimisations
Move global constants to a separate constants file. Component-specific constants into a constant file inside the component folder.
Never call a functional Component like a simple function Sanitise HTML to avoid XSS attacks
Subscribe to my newsletter
Read articles from Vishesh Tiwari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Vishesh Tiwari
Vishesh Tiwari
Vishesh Tiwari is a dedicated IT professional with over 5 years of experience. Specializing in the Java Spring Boot and React JS tech stack, Vishesh excels as a Full Stack Java Developer. His skills cover both front-end and back-end development, enabling him to create robust and scalable applications. Additionally, Vishesh has gained valuable experience working with AWS for a year, enhancing his ability to leverage cloud services. Passionate about coding and continuous learning, he stays updated with the latest industry trends and best practices. Connect with Vishesh to explore insights on full stack development and innovative technology.