Component Lifecycle

Overview

Components in Now.js go through a series of lifecycle stages from initialization to destruction. Understanding these stages is crucial for managing component behavior and resource handling.

Component Lifecycle Diagram

Component Lifecycle Flow Diagram

Lifecycle Stages

1. Creation Phase

beforeCreate

Called before the component instance is created. Good for setting up initial configurations.

const MyComponent = {
  beforeCreate() {
    // Setup initial configurations
    console.log('Component is about to be created');
  }
};

created

Called after the component instance is created but before mounting. Access to reactive data and events is now available.

const MyComponent = {
  created() {
    // Initialize data or setup event listeners
    this.loadInitialData();
    this.setupEventListeners();
  }
};

2. Mounting Phase

beforeMount

Called right before the component is inserted into the DOM.

const MyComponent = {
  beforeMount() {
    // Prepare for DOM insertion
    // Access this.element (null at this point)
  }
};

mounted

Called after the component is inserted into the DOM. Perfect for DOM manipulations and integrations.

const MyComponent = {
  mounted() {
    // Component is now in DOM
    // this.element is available
    this.setupThirdPartyLibrary();
    this.focusInput();
  }
};

3. Updating Phase

beforeUpdate

Called before the component updates due to data changes.

const MyComponent = {
  beforeUpdate() {
    // Access to old DOM state
    const oldHeight = this.element.offsetHeight;
    this.saveScrollPosition();
  }
};

updated

Called after the component's DOM has been updated.

const MyComponent = {
  updated() {
    // DOM is now updated
    this.restoreScrollPosition();
    this.updateCharts();
  }
};

4. Destruction Phase

beforeDestroy

Called right before a component is destroyed. Good for cleanup tasks.

const MyComponent = {
  beforeDestroy() {
    // Cleanup tasks
    this.removeEventListeners();
    this.disconnectWebsocket();
  }
};

destroyed

Called after a component has been destroyed.

const MyComponent = {
  destroyed() {
    // Final cleanup
    // Component is removed from DOM
    console.log('Component destroyed');
  }
};

Error Handling

errorCaptured

Special lifecycle hook for handling errors in child components.

const MyComponent = {
  errorCaptured(error, component) {
    // Handle or log error
    console.error(`Error in component ${component.name}:`, error);
    // Return false to stop error propagation
    return false;
  }
};

Best Practices

Creation & Setup

Updates & State Management

Cleanup

Complete Example

const UserProfile = {
  // Configuration
  name: 'user-profile',

  // Initial state
  state: {
    user: null,
    loading: true
  },

  // Lifecycle hooks
  beforeCreate() {
    console.log('Setting up component...');
  },

  created() {
    // Initialize data
    this.loadUserData();
  },

  beforeMount() {
    console.log('Preparing DOM insertion...');
  },

  mounted() {
    // Setup after DOM insertion
    this.setupScrollHandlers();
    this.startAutoRefresh();
  },

  beforeUpdate() {
    console.log('Component is about to update...');
  },

  updated() {
    // Handle DOM updates
    this.updateUserInterface();
  },

  beforeDestroy() {
    // Cleanup
    this.stopAutoRefresh();
    this.removeScrollHandlers();
  },

  destroyed() {
    console.log('Component cleanup complete');
  },

  // Error handling
  errorCaptured(error) {
    this.notifyError(error);
    return false;
  },

  // Methods
  methods: {
    async loadUserData() {
      try {
        const response = await fetch('/api/user');
        this.state.user = await response.json();
      } catch (error) {
        this.handleError(error);
      } finally {
        this.state.loading = false;
      }
    },

    startAutoRefresh() {
      this.refreshInterval = setInterval(() => {
        this.loadUserData();
      }, 60000);
    },

    stopAutoRefresh() {
      clearInterval(this.refreshInterval);
    },

    setupScrollHandlers() {
      this.scrollHandler = () => {
        // Handle scroll events
      };
      window.addEventListener('scroll', this.scrollHandler);
    },

    removeScrollHandlers() {
      window.removeEventListener('scroll', this.scrollHandler);
    },

    updateUserInterface() {
      // Update UI based on new state
    },

    handleError(error) {
      console.error('Error in UserProfile:', error);
    }
  }
};

Common Patterns

Data Loading

const DataComponent = {
  created() {
    this.loadData();
  },

  methods: {
    async loadData() {
      this.state.loading = true;
      try {
        const data = await this.fetchData();
        this.state.data = data;
      } catch (error) {
        this.state.error = error;
      } finally {
        this.state.loading = false;
      }
    }
  }
};

Event Handling

const EventComponent = {
  mounted() {
    this.addEventListeners();
  },

  beforeDestroy() {
    this.removeEventListeners();
  },

  methods: {
    addEventListeners() {
      this.handler = this.handleEvent.bind(this);
      window.addEventListener('resize', this.handler);
    },

    removeEventListeners() {
      window.removeEventListener('resize', this.handler);
    }
  }
};

Performance Considerations

Next Steps