Replies: 2 comments
-
Second question: How to populate data before component first render? I am searching around and found function View1(props) {
let count = 1;
const [state, setState] = useState({isLoading: true, posts: []});
const getData = async function() {
console.log(count++);
setState({...state, isLoading: true});
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {method: 'GET', credentials: 'same-origin', headers: {'Accept': 'application/json, text/javascript'}});
setState({...state, isLoading: false, posts: await response.json()});
};
return html`
<host>
<h2 class=${props.route == activeRoute ? "active" : "none"}>${props.title}</h2>
${state.isLoading ? html`loading...` :
html`${state.posts.map((post) => html`<h3>${post.id} - ${post.title}</h3>`)}`}
</host>
`;
}
const CompView1 = c(View1);
//I want like this
CompView1.onBeforeFirstRender = function() {
this.getData();
}
customElements.define("view-1", CompView1); |
Beta Was this translation helpful? Give feedback.
-
Hi, thanks for using Atomico, these are good questions: Answer to question 1:Your objective is valid, but Atomico does not allow you to inject html type content directly as children for security reasons, I share with you ways to achieve the desired objective: Option 1: This technical technique allows you to instantiate the tagName as an Element. const views = new Map();
views.set('/v1', 'view-1');
views.set('/v2', 'view-2');
let loadedViews = ['/v1','/v2'];
let activeRoute = '/v1';
function App() {
return html`<host>
${loadedViews.map(v => html`<${views.get(v)}/>`)}
</host>`;
} Option 2: This technique allows you to directly use the constructor of the webcomponent to instantiate it. const views = new Map();
views.set('/v1', CompView1);
views.set('/v2', CompView2);
let loadedViews = ['/v1','/v2'];
let activeRoute = '/v1';
function App() {
return html`<host>
${loadedViews.map(v => html`<${views.get(v)}/>`)}
</host>`;
} Option 3: Recommended when node children will not be manipulated, this is useful when implementing libraries like https://prismjs.com/, the const views = new Map();
views.set('/v1', '<view-1></view-1>');
views.set('/v2', '<view-2></view-2>');
let loadedViews = ['/v1','/v2'];
let activeRoute = '/v1';
function App() {
return html`<host>
${loadedViews.map(v => html`<div innerHTML=${${views.get(v)}}/>`)}
</host>`;
} Answer to question 2:Asynchronous loads should not block the rendering cycle, for all asynchronous loads it is recommended to use the useEffect hook, example: import { useEffect } from "atomico";
function View1(props) {
let count = 1;
const [state, setState] = useState({ isLoading: true, posts: [] });
const getData = async function () {
console.log(count++);
setState({ ...state, isLoading: true });
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "GET",
credentials: "same-origin",
headers: { Accept: "application/json, text/javascript" },
});
setState({ ...state, isLoading: false, posts: await response.json() });
};
useEffect(getData, []); // 👈 after the first render
return html`
<host>
<h2 class=${props.route == activeRoute ? "active" : "none"}>
${props.title}
</h2>
${state.isLoading
? html`loading...`
: html`${state.posts.map(
(post) => html`<h3>${post.id} - ${post.title}</h3>`
)}`}
</host>
`;
}
const CompView1 = c(View1);
customElements.define("view-1", CompView1); by the way I invite you to meet @atomico/hooks, this package has a series of utilities for managing routes and asynchrony, for example: import { c, html } from "atomico";
import { usePromise } from "@atomico/hooks/use-promise";
// Now you can use getData outside of Atomico
const getData = async function () {
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "GET",
credentials: "same-origin",
headers: { Accept: "application/json, text/javascript" },
});
return response.json();
};
function View1(props) {
const [result = [], status] = usePromise(getData, true); // 👈 after the first render
return html`<host>
${status === "pending"
? "loading..."
: result &&
html`${result.map(
(post) => html`<h3>${post.id} - ${post.title}</h3>`
)}`}
</host>`;
}
const CompView1 = c(View1);
customElements.define("view-1", CompView1); Thank you for your questions and I invite you to join discord https://discord.gg/7z3rNhmkNE |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi @UpperCod
Let's say I have an array named loadedViews which is dynamic. The main app will render
views
bases on that, for example:The thing is, I want to make
App
dynamically render like thisBut it's just rendered as text
<view-1></view-1><view-2></view-2>
I have setup this codepen https://codepen.io/ali33yukisakura/pen/rNpJjGa?editors=1011
Beta Was this translation helpful? Give feedback.
All reactions