---
agentTools:
  projectIndex: https://whsjs.readme.io/llms.txt
---

# Component

[core / Component.js](https://github.com/WhitestormJS/whitestorm.js/blob/dev/src/framework/core/Component.js)

`Component` is a main class which is commonly used in core parts of **WhitestormJS framework**. `Component` is used in `MeshComponent` and almost all known classes of framework.

[block:callout]
{
  "type": "info",
  "body": "**Meshes, Lights, Cameras** are based on `Component` class.",
  "title": "Quick tip"
}
[/block]

[block:code]
{
  "codes": [
    {
      "code": "import THREE from 'three';\n\n// Basic component class.\nimport {Component} from 'whitestormjs/core/Component';\n\nclass EmptyComponent extends Component {\n  build() {\n    return new THREE.Object3D(); \n  }\n}\n\nconst myEmptyElement = new EmptyComponent();",
      "language": "javascript"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "basic",
  "title": "Defaults & instructions"
}
[/block]

When we call super - we should pass params object there. And we can also specify **defaults** object to fill required properties.

[block:code]
{
  "codes": [
    {
      "code": "// ...\n\nclass Dinosaur extends Component {\n  static defaults = {\n    teethCount: 32\n  };\n\n  // ...\n}\n\nconst saurolophus = new Dinosaur({teethCount: 56});\nsaurolophus.params.teethCount // -> 56\n\nconst dino = new Dinosaur();\ndino.params.teethCount // -> 32",
      "language": "javascript"
    }
  ]
}
[/block]

And sometimes we need to make simplified record, you may use instructions for that:

[block:code]
{
  "codes": [
    {
      "code": "// ...\n\nclass Star extends Component {\n  static defaults = {\n    direction: {x: 1, y: 0, z: 0}\n  };\n\n  static instructions = {\n    direction: ['x', 'y', 'z']\n  };\n\n\tconstructor(params = {}) {\n    super(params, Star.defaults, Star.instructions);\n  }\n\n  // ...\n}\n\n// After you can use it as here:\nconst sun = new Star({direction: [0, 1, 0]})\n\n// Or as usually:\nconst sun = new Star({direction: {x: 0, y: 1, z: 0}});",
      "language": "javascript"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "basic",
  "title": "Properties"
}
[/block]

### `.params`

An object that contains parameters.

### `.native`

A three.js object linked to the component.

### `.children`

Obnject's children (components)

[block:api-header]
{
  "type": "basic",
  "title": "Methods"
}
[/block]

[block:api-header]
{
  "type": "fn",
  "title": ".updateParams( object )"
}
[/block]

Every component has it's own params that it uses in further operations (such as building a geometry, material or linking to other object). For this we have a `.params` property that after you define a component is filled with defaults modified by values you passed.

`.updateParams()` extends this object with provided new values.

[block:code]
{
  "codes": [
    {
      "code": "// Lets imagine myEmptyElement.params -> {a: 2, b: 4}\n\nmyEmptyElement.updateParams({c: 3}) // -> {a: 2, b: 4, c: 3}\nmyEmptyElement.updateParams({b: 5}) // -> {a: 2, b: 5, c: 3}",
      "language": "javascript"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "fn",
  "title": ".addTo( parent )"
}
[/block]

As we work in 3D space - we have a World and objects that it should contain. All those object are called it's *children* . A world object will be a *parent* of other objects.

When we created a component we just described what it should be. But `WHS.World` is not yet linked to object we want to see on scene.

[block:code]
{
  "codes": [
    {
      "code": "myEmptyElement.addTo(world);",
      "language": "javascript"
    }
  ]
}
[/block]

Now we added our component to the scene. If you debug `world.scene.children` now - you can see that we have a `THREE.Object3D` in this array.

[block:api-header]
{
  "type": "fn",
  "title": ".copy( source )"
}
[/block]

This method is used to copy `.native` and `.params` from other `WHS.Component`.

[block:callout]
{
  "type": "warning",
  "body": "This method's code is different in pair with decorators like `MeshComponent`, `PhysicsComponent` and `SoftbodyComponent`."
}
[/block]

[block:code]
{
  "codes": [
    {
      "code": "const ball = MeshComponent(new WHS.Component(\n  new THREE.Mesh(\n    new THREE.SphereGeometry(3, 16, 16),\n    new THREE.MeshBasicMaterial({color: 0xffffff})\n  )\n));\n\nmyEmptyElement.copy(ball);\n\n// Now:\n// - myEmptyElement.params is a copy of ball.params\n// - myEmptyElement.native is a copy of ball.native",
      "language": "javascript"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "fn",
  "title": ".clone()"
}
[/block]

Clone method works directly with `.copy()` method. That's what it does:

[block:code]
{
  "codes": [
    {
      "code": "  // Component.js\n  // ... \n\n  clone() {\n    return new Component(this.params).copy(this);\n  }\n\n  // ...",
      "language": "javascript"
    }
  ]
}
[/block]

Uasge of `.clone()`:

[block:code]
{
  "codes": [
    {
      "code": "// Let's take \"ball\" this time as it has .native;\n\nconst ball2 = ball.clone();\nball2.position.y += 10;\n\nball2.addTo(world);",
      "language": "javascript"
    }
  ]
}
[/block]