Skip to content
Functional Component like React, but for Web Components.
TypeScript JavaScript
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/workflows
fuco
html
server
src Server Side Rendering for Context (#41) Apr 1, 2020
.eslintrc.json
.gitignore
CHANGELOG.md
LICENSE
README.md
karma.conf.js
package-lock.json
package.json
rollup.config.js
tsconfig.json
tsconfig.test.json

README.md

fuco

npm install size test codecov

Functional Component like React, but for Web Components.

<!DOCTYPE html>
<html lang="en">
  <body>
    <counter-app></counter-app>
    <script type="module">
      import { html, defineElement, useState } from "//unpkg.com/fuco?module";

      function Counter() {
        const [count, setCount] = useState(0);
        return html`
          <div>${count}</div>
          <button @click=${() => setCount(count + 1)}>+</button>
          <button @click=${() => setCount(count - 1)}>-</button>
        `;
      }

      defineElement("counter-app", Counter);
    </script>
  </body>
</html>

Installation

npm install fuco
# or use yarn
yarn add fuco

Hooks

useAttribute

useAttribute returens attribute value, and updates the component when the attribute specified by the first argument is changed.

defineElement("greet-element", () => {
  const name = useAttribute("name");
  const hidden = useAttribute("hidden", value => value != null);
  if (hidden) {
    return html``;
  }
  return html`
    <div>Hello, ${name}</div>
  `;
});

html`
  <greet-element name="World"></greet-element>
`;
// => `<div>Hello, World</div>`

html`
  <greet-element name="WebComponent" hidden></greet-element>
`;
// => ``

useProperty

useProperty returns element's property value, and updates the component when the property values is changed.

defineElement("card-element", () => {
  const card = useProperty("card");
  return html`
    <div>${card.mark} ${card.value}</div>
  `;
});

const heartAce = { mark: "♥", value: 1 };
html`
  <card-element .card=${heartAce}></card-element>
`;

useDispatchEvent

useDispatchEvent offers dispatch function like dispatchEvent to use CustomEvent.

defineElement("send-message", () => {
  const dispatch = useDispatchEvent("some-message", {
    bubbles: true,
    composed: true
  });
  return html`
    <button @click=${() => dispatch("Hi!")}>Send</button>
  `;
});

// You can listen custom event using `@` prefix.
html`
  <send-message @some-message=${e => console.log(e.detail)}></send-message>
`;

useStyle

useStyle can adapt a StyleSheet to the component.

function HelloWorld() {
  useStyle(
    () => css`
      div {
        color: red;
      }
    `
  );
  return html`
    <div>Hello, world</div>
  `;
}

useState

useState returns a pair of state and setter function, and upadates the component by updating state using setter function.

function Counter() {
  const [count, setCount] = useState(0);
  return html`
    <div>${count}</div>
    <button @click=${() => setCount(count + 1)}>PLUS</button>
  `;
}

useReducer

useReducer returns a pair of state and dispatch function.

function Counter() {
  const [count, dispatch] = useReducer((state, action) => state + action, 0);
  return html`
    <div>${count}</div>
    <button @click=${() => dispatch(1)}>PLUS</button>
  `;
}

useRef

useRef returned a ref object like React's, and you can recieve a DOM by setting ref object to attribute.

function Input() {
  const [value, setValue] = useState("");
  const inputRef = useRef(null);
  return html`
    <input :ref=${inputRef} />
    <button @click=${() => setValue(inputRef.current.value)}>push</button>
  `;
}

useContext

createContext offers Context, and usingContext.defineProvider to define provider, and you can consume it using useContext(Context).

const ThemeContext = createContext();

// define a custom element as Provider
ThemeContext.defineProvider("theme-provider");

const App = () => html`
  <theme-provider .value=${"dark"}>
    <theme-comsumer></theme-comsumer>
  </theme-provider>
`;

// consume context
defineElement("theme-consumer", () => {
  const theme = useContext(ThemeContext);
  return html`
    <div>theme is ${theme}</div>
  `;
});

useEffect

useEffect gives you a side effects. it will run after rendering the component.

function Timer() {
  useEffect(() => {
    const id = setInterval(() => console.log("interval"));
    return () => clearInterval(id);
  }, []);
  return html``;
}

useLayoutEffect

useLayoutEffect runs after the DOM has been updated, but before the browser has had a chance to paint those changes

function Box() {
  const ref = useRef(null);
  useLayoutEffect(() => {
    ref.current.style.top = "100px";
  });
  return html`
    <div :ref=${ref}></div>
  `;
}

useMemo

useMemo returns a memorized value. the value will update when deps given as the second argument.

function Plus() {
  const value = useMemo(() => a + b, [a, b]);
  return html`
    ${value}
  `;
}

useCallback

useCallback returns memorized callback as same as useMemo.

function Greet() {
  const greet = useCallback(() => alert("Hello"));
  return html`
    <button @click=${greet}>hello</button>
  `;
}

License

MIT

You can’t perform that action at this time.