How to Refactor a Complex React Component for Easy Relocation

This article walks through a real‑world micro‑refactor of a React page, detailing the analysis of component dependencies, the step‑by‑step extraction of a tangled UI block into a reusable component, and the testing strategy that ensures the new code works without breaking existing functionality.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
How to Refactor a Complex React Component for Easy Relocation

Requirement Background

A page needed a UI block (highlighted in red) moved to a new location, as shown in the before/after screenshot.

Requirement Evaluation

At first glance the task seemed trivial—just shift a component—but the existing code revealed hidden complexity. The page consists of components A and B . Component A contains sub‑components a1 and a2 , and the target position lies between them. The UI block to move, called b1 , lives inside B but is not a standalone component; it mixes two conditional components ( AR and HR ) and depends on ten properties from B 's context.

Refactor Purpose

Isolate the b1 logic into a movable component.

Improve code readability to lower the cost of understanding.

Preserve existing functionality.

Refactor Process

1. Make AR component independent

Original AR code inside B :

class ARecord extends React.Component {
  openARecord = () => {
    const openUrl = `${getBaseUrl()}#/list`;
    openLink(openUrl);
  };
  render() {
    return (
      <div className="content" onClick={this.openARecord}>...</div>
    );
  }
}

New, extracted AR component with explicit props:

// Interface for props
interface IARecordProps {
  className?: string;
  style?: object;
  context: IContextModel;
  componentProps: { id: string; pId: string };
}

export default function ARecord(props: IARecordProps) {
  const { className, style = {}, context, componentProps } = props;
  const { utSpace } = context;
  const { id, pId } = componentProps;
  const openARecord = (id: string, pId: string) => {
    const openUrl = `${getBaseUrl()}#/arecordlist`;
    openLink(openUrl);
  };
  return (
    <div className="content" onClick={() => openARecord(id, pId)}>
      ...
    </div>
  );
}

2. Page functional test

Added the new ARecord to the original location in B and verified the page behaved as before.

3. Encapsulate b1 as a new component

Defined data models:

// b1 data model
interface IHRecordSummaryData {
  hasSupplySuite: () => boolean;
  id: string;
  pId: string;
  type: TypeEnum;
  data: {};
  count: number;
  name: string;
  username: string;
  code: string;
  isUserInList: () => boolean;
}

// b1 component props
interface IHRecordSummaryProps {
  className?: string;
  style?: object;
  context: IContextModel;
  componentProps: IHRecordSummaryData;
}

Implementation (simplified):

export default function HRecordSummary(props: IHRecordSummaryProps) {
  const { context, componentProps } = props;
  const { id, pId, type, data, count, name, username, code, hasSupplySuite, isUserInList } = componentProps || {};
  const getComponentNode = (cp) => {
    if (type === TypeENUM.REPAIR_CHECK && data && !hasSupplySuite) {
      return <ARecord context={context} componentProps={{ id, pId }} />;
    }
    if (hasSupplySuite || type > 1) {
      return (
        <HRecord
          pId={pId}
          id={id}
          count={count}
          name={name}
          username={username}
          isLeave={type === TypeEnum.LEAVE}
          code={code}
        />
      );
    }
    if (!isUserInList || location.href.indexOf('list') !== -1) {
      return null;
    }
    return null;
  };
  return <div>{getComponentNode(componentProps)}</div>;
}

4. Reduce API surface

Combined the ten properties passed from Page → B → b1 into a single object, decreasing B 's API count from 37 to 29.

5. Simplify data handling

Replaced two method props with their boolean results and turned a large data object into a simple boolean flag, further shrinking the component contract.

6. Continuous testing

After each refactor step, functional tests were run and passed, ensuring no regression.

Conclusion

By extracting tangled logic into well‑defined, type‑safe components and consolidating APIs, the code became easier to understand, maintain, and relocate. The final test suite confirmed that the new structure works correctly, illustrating how even small daily requirements are opportunities for incremental code improvement.

"Any fool can write code that a computer understands; only a great programmer writes code that humans can understand." – Martin Fowler

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendTypeScriptReactComponent Design
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology innovations.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.