> ## Documentation Index
> Fetch the complete documentation index at: https://docs.starknet.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction to components

Components are like modular addons that can be snapped into contracts to add reusable logic, storage, and events.
They are used to separate the core logic from common functionalities, simplifying the contract's code and making it easier to read and maintain.
It also reduces the risk of bugs and vulnerabilities by using well-tested components.

Key characteristics:

* Modularity: Easily pluggable into multiple contracts.
* Reusable Logic: Encapsulates specific functionalities.
* Not Standalone: Cannot be declared or deployed independently.

## How to create a component

The following example shows a simple `Switchable` component that can be used to add a switch that can be either on or off.
It contains a storage variable `switchable_value`, a function `switch` and an event `Switch`.

<Note>
  It is a good practice to prefix the component storage variables with the component name to [avoid collisions](./collisions).
</Note>

```rust theme={null}
#[starknet::interface]
pub trait ISwitchable<TContractState> {
    fn is_on(self: @TContractState) -> bool;
    fn switch(ref self: TContractState);
}

#[starknet::component]
pub mod switchable_component {
    use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};

    #[storage]
    pub struct Storage {
        switchable_value: bool,
    }

    #[derive(Drop, Debug, PartialEq, starknet::Event)]
    pub struct SwitchEvent {}

    #[event]
    #[derive(Drop, Debug, PartialEq, starknet::Event)]
    pub enum Event {
        SwitchEvent: SwitchEvent,
    }

    #[embeddable_as(Switchable)]
    impl SwitchableImpl<
        TContractState, +HasComponent<TContractState>,
    > of super::ISwitchable<ComponentState<TContractState>> {
        fn is_on(self: @ComponentState<TContractState>) -> bool {
            self.switchable_value.read()
        }

        fn switch(ref self: ComponentState<TContractState>) {
            self.switchable_value.write(!self.switchable_value.read());
            self.emit(Event::SwitchEvent(SwitchEvent {}));
        }
    }

    #[generate_trait]
    pub impl SwitchableInternalImpl<
        TContractState, +HasComponent<TContractState>,
    > of SwitchableInternalTrait<TContractState> {
        fn _off(ref self: ComponentState<TContractState>) {
            self.switchable_value.write(false);
        }
    }
}
```

A component is really similar to a contract and can also have:

* An interface defining entrypoints (`ISwitchableComponent<TContractState>`)
* A Storage struct
* Events
* Internal functions

It doesn't have a constructor, but you can create an `_init` internal function and call it from the contract's constructor. In the previous example, the `_off` function will be used this way.

<Note>
  It's currently not possible to use the same component multiple times in the same contract.
  This is a known limitation that may be lifted in the future.

  For now, you can view components as implementations of specific interfaces or features (`Ownable`, `Upgradeable`, ... \~`able`).
  This is why we called the component in the above example `Switchable`, and not `Switch`; the contract *is switchable*, it does not *have a switch*.
</Note>

## How to use a component

Now that we have a component, we can use it in a contract.
The following contract incorporates the `Switchable` component:

```rust theme={null}
#[starknet::contract]
pub mod SwitchContract {
    use super::switchable_component;

    component!(path: switchable_component, storage: switch, event: SwitchableEvent);

    #[abi(embed_v0)]
    impl SwitchableImpl = switchable_component::Switchable<ContractState>;

    #[storage]
    struct Storage {
        #[substorage(v0)]
        switch: switchable_component::Storage,
    }

    #[event]
    #[derive(Drop, Debug, PartialEq, starknet::Event)]
    pub enum Event {
        SwitchableEvent: switchable_component::Event,
    }

    // You can optionally use the internal implementation of the component as well
    impl SwitchableInternalImpl = switchable_component::SwitchableInternalImpl<ContractState>;

    #[constructor]
    fn constructor(ref self: ContractState) {
        // Internal function call
        self.switch._off();
    }
}
```

## How to test a component

In order to effectively test a component, you need to test it in the context of a contract.
A common practice is to declare a `Mock` contract that has the only purpose of testing the component.

To test the `Switchable` component, we can use the previous `SwitchableContract`:

```rust theme={null}
#[cfg(test)]
mod test {
    use super::{ISwitchableDispatcher, ISwitchableDispatcherTrait};
    use snforge_std::{
        ContractClassTrait, DeclareResultTrait, declare, spy_events, EventSpyAssertionsTrait,
    };
    use super::SwitchContract; // Used as a mock contract
    use super::switchable_component;

    fn deploy() -> ISwitchableDispatcher {
        let contract = declare("SwitchContract").unwrap().contract_class();
        let (contract_address, _) = contract.deploy(@array![]).unwrap();
        ISwitchableDispatcher { contract_address }
    }

    #[test]
    fn test_constructor() {
        let switchable = deploy();
        assert_eq!(switchable.is_on(), false);
    }

    #[test]
    fn test_switch() {
        let switchable = deploy();
        let mut spy = spy_events();
        switchable.switch();
        assert_eq!(switchable.is_on(), true);

        spy
            .assert_emitted(
                @array![
                    (
                        switchable.contract_address,
                        SwitchContract::Event::SwitchableEvent(
                            switchable_component::Event::SwitchEvent(
                                switchable_component::SwitchEvent {},
                            ),
                        ),
                    ),
                ],
            );
    }

    #[test]
    fn test_multiple_switches() {
        let switchable = deploy();
        switchable.switch();
        assert_eq!(switchable.is_on(), true);
        switchable.switch();
        assert_eq!(switchable.is_on(), false);
        switchable.switch();
        assert_eq!(switchable.is_on(), true);
    }
}
```

## Deep dive into components

You can find more in-depth information about components in [The Cairo book - Components](https://book.cairo-lang.org/ch16-02-00-composability-and-components.html).
