Skip to main content

Patterns: Components

Functional component structure, PropTypes, import ordering, state-management layers, forms, and file/folder naming. Load via the patterns-components context group.

Structure

All components are functional with hooks. No class components (one legacy HOC exception in Charts/autoHeight.js).

Props are typed with PropTypes (bottom of file):

MyComponent.propTypes = {
data: PropTypes.object,
isLoading: PropTypes.bool,
onSubmit: PropTypes.func,
};

Default props use destructuring defaults (no .defaultProps):

const MyComponent = ({ avatarSize = 24, showName = true }) => { ... };

Import Ordering

Consistent 3-section + local constants pattern:

// Core imports
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useTranslation } from 'react-i18next';

// Component imports
import { Button, Form, Input, Typography } from 'antd';
import MyComponent from '../components/UI/MyComponent';

// Misc imports
import { useUserPermissions } from '../utils/hooks/useUserPermissions';
import { PERMISSIONS_ORG } from '../constants/main';
import { useGetBotsQuery } from '../store/bots/botsApi';

// Constant declarations
const { Text, Title } = Typography;
const SOME_LOCAL_CONSTANT = 'value';

All imports are relative. No path aliases exist. All imports at the top of the file; never inside functions or conditionals.

State Management Layers

  1. RTK Query (server state): API files inject endpoints into a single apiSlice. Standard for all data fetching.
  2. Redux slices (client/socket state): authSlice, globalSlice, liveChatSlice, botsSlice, etc. Used for UI state and WebSocket-driven data.
  3. React Context (component subtree state): Used sparingly for tight component trees (LiveChatContext, GraphContext).
  4. useState (component-local state): Universal. useReducer is not used anywhere.

RTK Query patterns:

  • useGetXQuery() for auto-fetching
  • useLazyGetXQuery() for imperative fetching
  • useXMutation() for mutations
  • getCurrentQueryState() helper to read cached data without re-fetching
  • Cache invalidation via tag-based system (API_TAGS in constants/api.js)

Form Handling

Ant Design Form exclusively. No React Hook Form or Formik.

const [form] = Form.useForm();

<Form form={form} layout="vertical" onFinish={handleSubmit} initialValues={initialValues}>
<Form.Item name="email" rules={[{ required: true, type: 'email' }]}>
<Input />
</Form.Item>
</Form>

Server-side errors injected via form.setFields([{ name, errors }]).

Parent-controlled forms pass the form instance as a prop for external submit triggers.

File and Folder Naming

CategoryConventionExamples
Component filesPascalCase.jsxBotScreen.jsx, MessageNode.jsx, LiveChatMessenger.jsx
Icon filesPascalCase.jsHelviaIcon.js, LiveChatIcon.js
Utility directoriescamelCase/index.jsutils/string/replaceUrlParams/index.js
Hook directoriescamelCase/index.jsutils/hooks/useBotLanguage/index.js
Style fileslowercase.lesslivechat.less, forms.less, layout.less
Constant filescamelCase.jsflowGraph.js, liveChat.js
Store featurescamelCase dir, featureApi.js / featureSlice.js / featureActions.js / featureMessages.jsstore/bots/botsApi.js
Test files.test.jsOnly in utils/is/ and utils/array/

No index.jsx component pattern. Each component is its own named file.