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>
npm install fuco
# or use yarn
yarn add fuco
-
Original Hooks
-
React Hooks compatible
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
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
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
can adapt a StyleSheet to the component.
function HelloWorld() {
useStyle(
() => css`
div {
color: red;
}
`
);
return html`
<div>Hello, world</div>
`;
}
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
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
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>
`;
}
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
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
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
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
returns memorized callback as same as useMemo
.
function Greet() {
const greet = useCallback(() => alert("Hello"));
return html`
<button @click=${greet}>hello</button>
`;
}
MIT