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.
-
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