Make your React more Object-Oriented Programming

bharathraj.eth
3 min readMay 21, 2023

--

  1. Component-based approach: React’s component model aligns well with OOP concepts. Treat React components as classes, with each component encapsulating its state and behaviour.
class MyComponent extends React.Component {
// Component code
}

2. Class components: Use class components instead of functional components when applying OOP principles. Class components provide a way to define lifecycle methods, maintain state, and implement inheritance.

class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

render() {
return <div>{this.state.count}</div>;
}
}

3. Single Responsibility Principle (SRP): Aim for components that have a single responsibility. Divide complex components into smaller, reusable ones that focus on specific tasks. This promotes modularity and enhances code maintainability.

// Complex component
class ProductList extends React.Component {
// ...
}

// Split into smaller components
class ProductList extends React.Component {
// ...
}

class ProductItem extends React.Component {
// ...
}

4. Inheritance and composition: Utilize inheritance and composition to promote code reuse and abstraction. Inheritance allows you to create a base component with shared functionality, while composition enables you to combine multiple components to create more complex ones.

class BaseComponent extends React.Component {
// Base component functionality
}

class ChildComponent extends BaseComponent {
// Child component specific functionality
}

// Composition
const ComplexComponent = () => {
return (
<div>
<ChildComponent />
<OtherComponent />
</div>
);
}

5. State management: Follow the principle of encapsulating state within components. Keep the state local to the component unless it needs to be shared with other components, in which case you can lift the state up to a common ancestor component or use a state management library like Redux or MobX.

class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

increment() {
this.setState((prevState) => ({
count: prevState.count + 1
}));
}

render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.increment()}>Increment</button>
</div>
);
}
}

6. Use lifecycle methods: Take advantage of React’s lifecycle methods to control component behavior during different stages, such as initialization, mounting, updating, and unmounting. This allows you to perform actions like fetching data, setting up subscriptions, or cleaning up resources when necessary.

class MyComponent extends React.Component {
componentDidMount() {
// Perform actions after the component is mounted
}

componentDidUpdate(prevProps, prevState) {
// Perform actions after the component's props or state update
}

componentWillUnmount() {
// Perform cleanup actions before the component is unmounted
}

render() {
// Render the component
}
}

7. Encapsulate component behavior: Define methods within components to encapsulate behavior and keep related functionality together. These methods can handle event handling, data manipulation, or any other logic specific to the component.

class ToggleButton extends React.Component {
constructor(props) {
super(props);
this.state = {
isOn: false
};
}

handleClick() {
this.setState((prevState) => ({
isOn: !prevState.isOn
}));
}

render() {
return (
<button onClick={() => this.handleClick()}>
{this.state.isOn ? "ON" : "OFF"}
</button>
);
}
}

8. Use class properties and arrow functions: Leverage class properties and arrow functions to avoid potential issues with binding the this keyword. By using arrow functions for event handlers and class properties for methods, you can ensure that the correct context is maintained without the need for explicit binding.

class MyComponent extends React.Component {
myMethod = () => {
// Method implementation
};

render() {
return <button onClick={this.myMethod}>Click</button>;
}
}

9. Utilize inheritance for code reuse: If you find yourself repeating code across components, consider creating a base component that encapsulates the shared functionality. Then, have other components extend this base component to inherit its behavior.

class BaseComponent extends React.Component {
// Shared functionality
}

class ChildComponent extends BaseComponent {
// Inherits shared functionality from BaseComponent
}

10. Use proper naming conventions: Follow standard naming conventions for classes, methods, and variables to improve code readability and maintainability. This includes using descriptive and meaningful names that accurately reflect the purpose and functionality of the components and methods.

class ProductList extends React.Component {
// ...
}

class ShoppingCart extends React.Component {
// ...
}

Follow: 🐤 https://twitter.com/rajdxb14

--

--