LogoLogo
GithubTwitterDiscordPlayground
English
English
  • 👋Atomico
  • 🚀Getting started with Atomico
  • ⚛️Getting started with Atomico for React users
  • 💡What can you do with Atomico?
    • You can create amazing webcomponents
    • You can create design systems
    • You can create websites
    • You can create mobile applications
    • You can create web applications
  • API
    • 🧬Props(Properties)
      • Value cycle as prop
      • Is it advisable to declare events using the props API?
    • 🧩VirtualDOM
      • Advanced
    • 🎣Hooks
      • useProp
      • useEvent
      • useRef
      • useHost
      • useState
      • useReducer
      • useEffect, useLayoutEffect and useInsertionEffect
      • useMemo and useCallback
      • useUpdate
      • useId
      • useContext
        • useProvider
      • usePromise
      • useAsync and useSuspense
      • useAbortController
    • 🔬Testing
      • Render cycle
      • atomico/test-hooks
      • atomico/test-dom
  • Guides
    • 🤔Frequent questions
      • Is it advisable to declare events using the props API?
      • How to declare events for your component at the type level for TSX?
      • When and why to use shadowDom?
      • Can I use Atomico in browsers without ESM support?
    • 🤩Component
      • Naming
      • CSS Styles with Shadow DOM
    • 🛡️Atomico with Typescript
      • Props
      • Component
      • Meta-types
        • Type
        • Event declaration
        • Method declaration
      • Check the correct use of hooks
    • 🤝Atomico and React
      • Integrating Atomico in React
      • From React to Atomico
        • Rendering Differences
        • VirtualDOM api differences
    • ⏳Atomico and Asynchrony
    • 🧠Atomico design patterns
      • ♻️Webcomponents with hybrid rendering
      • 🔗Slot as templates
      • 🔀Slot
    • 📖Atomico and Storybook
      • Frequent questions
    • 💧SSR / SSG
    • 🗃️Archives
      • Class inheritance
      • Forms and shadowDOM
      • Tips
      • Design systems
      • Atomico style guide
        • File structure
          • Monorepo
          • Design systems
  • packages
    • @atomico/hooks
      • useCurrentValue
      • use-intersection-observer
      • use-ref-values
      • use-script
      • use-attributes
      • use-prop-proxy
      • use-click-press
      • use-dollars
      • use-reflect-event
      • use-keyboar
      • use-click-coordinates
      • use-copy
      • use-debounce-state
      • use-form
      • use-listener
      • use-disabled
      • use-css
      • use-channel
      • use-promise
      • use-responsive-state
      • use-parent
      • use-resize-observer
      • use-slot
        • useSlot
        • useProxySlot
      • use-render
      • use-mutation-observer
      • use-css-light-dom
      • use-controller
      • use-router
      • use-async-effect
      • use-child-nodes
      • use-force-render
    • @atomico/store
      • Store
    • @atomico/storybook
    • @atomico/router
    • @atomico/vite
      • ⚙️Process CSS tag template blocks with PostCSS.
      • 🏗️Compile your code to be distributed optimally as a package.
      • 📕Use the JSX/TSX syntax of Atomico when using Storybook.
      • 🤖Automatically create customElements.define
      • ☑️Support for Vitest for Atomico.
      • 🧙‍♂️Server actions
    • @atomico/exports
      • 🚩CLI and Flags
      • 🤖Wrapper for React
    • @atomico/components
      • @atomico/keen-slider
      • @atomico/modal
      • @atomico/lottie
      • @atomico/table
    • @atomico/react
    • @atomico/postcss-tokens
      • Example with @atomico/vite
    • @atomico/wrapper
    • 🚫Deprecated
      • @atomico/magic-form
        • MagicFormProvider | <magic-form-provider>
        • MagicForm | <magic-form>
        • MagicForm Hooks
        • MagicForm in React and Preact
        • MagicForm in Microfrontend
        • MagicForm Patterns
      • @atomico/design-tokens
        • @atomico/design-tokens api
  • Support
    • Discord
    • Github
    • Twitter
Powered by GitBook
On this page
  • If you develop with React, you will know 80% Atomico ... now why use Atomico?:
  • Counter example
  • CustomHooks example
  • CSS-in-JS

Was this helpful?

Edit on GitHub
Export as PDF
  1. Guides
  2. Atomico and React

From React to Atomico

Atomico inherits part of the React syntax and applies it to webcomponents, with a closer to standard approach.

If you develop with React, you will know 80% Atomico ... now why use Atomico?:

  1. Atomico will not limit your React learning curve, what you learned in Atomico is applicable in React, for example hooks and virtualDOM.

  2. Atomico is 3kB in size which is 7% of React + React-dom.

  3. Better component abstraction, for example the use of the ShadowDOM will avoid the need to use css-in-js like styles-components or emotion, reducing dependencies.

  4. Agnostic Components, what you create with React only works within React, what you create with Atomico works on the web, so you can use your components within React, Vue, Svelte or Html.

  5. Exclusive component for React, the CLI @ atomico / exports automatically generates a wrapper component of your webcomponent for React, improving backward compatibility with React.

The following examples show some differences between React and Atomico.

Counter example

import { useState } from "react";
import ReactDOM from 'react-dom'

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}


render(
  <Counter initialCount={1}/>, 
  document.querySelector("#counter")
);
import { c, useProp } from "atomico";

function counter() {
  const [count, setCount] = useProp("count");
  return (
    <host>
      Count: {count}
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </host>
  );
}

counter.props = { count: { type: Number, value: 0 } }

const Counter = c(counter);

customElements.define(
  "my-counter",
  Counter  
);

From the example we will highlight the following differences:

  1. In Atomico you only use one import.

  2. useProp is like useState, but with the difference that useProp references the state from the webcomponent property defined in counter.props.

  3. counter.props allows us to create the properties of our webcomponent, these are like React's propTypes, but with a big difference they are associated with the instance and can be read and modified by referencing the node, example document.querySelector("my-counter").count = 10;

  4. ReactDom.render needs a reference to mount the component, in Atomico you only need to create the my-counter tag to create a new instance of the component.

  5. The <host/> tag is similar to <> </> for React, but <host/> represents the webcomponent instance and every component created with Atomico must return the host tag

  6. This is only readability, but in Atomico by convention we do not use capital letters when naming our component, these are only used when creating the customElement as in line 16, since Counter is instantiable.

CustomHooks example

import { useEffect, useState } from "react";

function useJsonPlaceholder(path) {
  const [state, setState] = useState();
  useEffect(() => {
    let cancel;
    setState(null);
    fetch(`https://jsonplaceholder.typicode.com/${path}`)
      .then(() => res.json())
      .then((data) => !cancel && setState( data ));
    return () => (cancel = true);
  }, [path]);
}

function Component() {
  const posts = useJsonPlaceholder("posts");
  return (
    <>
      {posts 
        ? posts.map(({ title }) => <h1>{title}</h1>)
        : "Loading..."}
    </>
  );
}
import { useEffect, useState } from "atomico";

function useJsonPlaceholder(path) {
  const [state, setState] = useState();
  useEffect(() => {
    let cancel;
    setState(null);
    fetch(`https://jsonplaceholder.typicode.com/${path}`)
      .then(() => res.json())
      .then((data) => !cancel && setState( data ));
    return () => (cancel = true);
  }, [path]);
}

function component() {
  const posts = useJsonPlaceholder("posts");
  return (
    <host>
      {posts 
        ? posts.map(({ title }) => <h1>{title}</h1>)
        : "Loading..."}
    </host>
  );
}

From the example we will highlight the following differences:

  1. The hook api is the same.

  2. the component in Atomico returns the `<host/> tag.

Supported hooks

In Atomico you will have the most useful React hooks such as:

  1. useRef

  2. useState

  3. useReducer

  4. useLayoutEffect

  5. useEffect

  6. useMemo

  7. useCallback

CSS-in-JS

It is common to see the use of libraries such as Emotion or styled-components to encapsulate styles in React, but these add an additional cost, be it for performance or bundle, in Atomico there is no such cost.

const Button = styled.a`
  /* This renders the buttons above... Edit me! */
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
  background: transparent;
  color: white;
  border: 2px solid white;

  /* The GitHub button is a primary button
   * edit this to target it specifically! */
  ${props => props.primary && css`
    background: white;
    color: black;
  `}
`

render(
  <div>
    <Button
      href="https://github.com/styled-components/styled-components"
      target="_blank"
      rel="noopener"
      primary
    >
      GitHub
    </Button>

    <Button as={Link} href="/docs">
      Documentation
    </Button>
  </div>
)
import { c, css } from "atomico";

function button() {
  return <host shadowDom><slot/></host>;
}

button.props = { primary: { type: Boolean, relfect: true } };

button.styles = css`
  :host {
    display: inline-block;
    border-radius: 3px;
    padding: 0.5rem 0;
    margin: 0.5rem 1rem;
    width: 11rem;
    background: transparent;
    color: white;
    border: 2px solid white;
  }

  :host([primary]) {
    background: white;
    color: black;
  }
`;

export const Button = c(button);

PreviousIntegrating Atomico in ReactNextRendering Differences

Last updated 1 year ago

Was this helpful?

useContext : Not supported, event api is better practice than context when using webcomponents, example ****

🤝
useChannel