geekelo / dsa_practice

This repo is maintained just for the purpose of daily data structures and algorithm practice and proficiency
1 stars 0 forks source link

Design patterns in React and JS #8

Open geekelo opened 5 months ago

geekelo commented 5 months ago

Design patterns are reusable solutions to common problems that arise during software development. They provide a general template to solve a particular problem that can be adapted to fit the needs of different scenarios. Understanding design patterns is essential for writing clean, maintainable, and scalable code. In this response, I'll focus on some commonly used design patterns in JavaScript and React.

JavaScript Design Patterns:

  1. Singleton Pattern:

    • Purpose: Ensures that a class has only one instance and provides a global point of access to it.
    • Example in JS:

      const Singleton = (function () {
      let instance;
      
      function createInstance() {
       // Private constructor logic
       return {
         getInstance: function () {
           if (!instance) {
             instance = createInstance();
           }
           return instance;
         },
       };
      }
      
      return {
       getInstance: function () {
         if (!instance) {
           instance = createInstance();
         }
         return instance;
       },
      };
      })();
      
      const instance1 = Singleton.getInstance();
      const instance2 = Singleton.getInstance();
      
      console.log(instance1 === instance2); // true
  2. Module Pattern:

    • Purpose: Encapsulates private and public members within a single module, providing a way to structure and organize code.
    • Example in JS:

      const Module = (function () {
      // Private variables
      let privateVar = 0;
      
      // Private function
      function privateFunction() {
       console.log('Private function');
      }
      
      return {
       // Public variables
       publicVar: 1,
      
       // Public function
       publicFunction: function () {
         privateVar++;
         privateFunction();
         console.log('Public function');
       },
      };
      })();
      
      console.log(Module.publicVar);
      Module.publicFunction();
  3. Observer Pattern:

    • Purpose: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
    • Example in JS:

      class Subject {
      constructor() {
       this.observers = [];
      }
      
      addObserver(observer) {
       this.observers.push(observer);
      }
      
      notifyObservers(data) {
       this.observers.forEach(observer => observer.update(data));
      }
      }
      
      class Observer {
      update(data) {
       console.log(`Received update: ${data}`);
      }
      }
      
      const subject = new Subject();
      const observer1 = new Observer();
      const observer2 = new Observer();
      
      subject.addObserver(observer1);
      subject.addObserver(observer2);
      
      subject.notifyObservers('Some data has changed');

React Design Patterns:

  1. Container-Component Pattern:

    • Purpose: Separates the concerns of data fetching (container) and rendering (component) in React applications.
    • Example in React:

      // Container component
      class UserContainer extends React.Component {
      constructor(props) {
       super(props);
       this.state = {
         userData: null,
       };
      }
      
      componentDidMount() {
       // Fetch user data
       // Update state with fetched data
      }
      
      render() {
       return <UserComponent userData={this.state.userData} />;
      }
      }
      
      // Presentational component
      const UserComponent = ({ userData }) => {
      // Render UI using userData
      return <div>{userData ? userData.name : 'Loading...'}</div>;
      };
  2. Render Props Pattern:

    • Purpose: Passes a function as a prop to a component, allowing the component to render with the logic provided by the function.
    • Example in React:

      class MouseTracker extends React.Component {
      constructor(props) {
       super(props);
       this.state = { x: 0, y: 0 };
      }
      
      handleMouseMove = (event) => {
       this.setState({ x: event.clientX, y: event.clientY });
      };
      
      render() {
       return (
         <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
           {this.props.render(this.state)}
         </div>
       );
      }
      }
      
      const App = () => (
      <MouseTracker
       render={({ x, y }) => (
         <div>
           <p>Mouse coordinates: ({x}, {y})</p>
         </div>
       )}
      />
      );
  3. Higher-Order Component (HOC) Pattern:

    • Purpose: A function that takes a component and returns a new component with additional props or behavior.
    • Example in React:

      const withLogger = (WrappedComponent) => {
      return class WithLogger extends React.Component {
       componentDidMount() {
         console.log(`Component ${WrappedComponent.name} is mounted`);
       }
      
       render() {
         return <WrappedComponent {...this.props} />;
       }
      };
      };
      
      const MyComponent = () => <div>My Component</div>;
      const MyComponentWithLogger = withLogger(MyComponent);

These examples provide a starting point for understanding and implementing design patterns in JavaScript and React. It's important to note that the choice of design pattern depends on the specific requirements and challenges of your application.