connectedCallback() cannot access self DOM elements - lit-element

console.log returns null.
It's unable to access to shadow DOM element after render.
class App extends LitElement{
render(){
return html`
<div class = "cont"> lorem </div>
`
}
connectedCallback(){
super.connectedCallback()
console.log(this.shadowRoot.querySelector(".cont"))
}
}
customElements.define('example-el', App)

When connectedCallback() is called, your component is not yet rendered because render() has not yet been called. You should use the firstUpdated() lifecycle callback instead. See this page for more details: https://lit-element.polymer-project.org/guide/events#where-to-add-your-event-listeners

Related

Use Same component multiple times failed. How can I get the thing done?

enter image description hereUse Same component multiple times failed. How can I get the thing done?
Why it's render only single element even though Multiple components Added.?
I use Todo Component multiple times in the Todos component, But it's give only just one element rendered.
Todo.js File 👇
import React, { Component } from 'react'
export default class Todo extends Component {
render() {
return (
<h3 className="text-dark text-center p-1 bg-light">
<i className="fas fa-times-circle fa-sm float-left mr-1 text-danger"></i> Task {this.props.num}
<input type="checkbox" className="mr-2 float-right"/>
</h3>
)
}
}
Todos.js file 👇
import React, { Component } from 'react'
import Todo from "./Todo"
export default class Todos extends Component {
render() {
return (
<div>
<Todo num="1"></Todo>
<Todo num="2"></Todo>
<Todo num="3"></Todo>
</div>
)
}
}
Output I got
Expected output

LitElement <slot> not wokring

I'm creating my custom accordion element. In which I'll have 2 components 1 for ul and other for li.
Content in file accordion-ul.ts, in which I've a slot where I want my li.
import { html, customElement, property, LitElement } from 'lit-element';
import { Accordion } from 'carbon-components';
#customElement('accordion-panel')
export default class AccordionPanel extends LitElement {
firstUpdated() {
const accordionElement = document.getElementById('accordion');
Accordion.create(accordionElement);
}
connectedCallback() {
super.connectedCallback();
}
render() {
return html`
<ul data-accordion class="accordion" id="accordion">
<slot></slot>
</ul>
`;
}
createRenderRoot() {
return this;
}
}
NOTE: I'm getting an error in the console in the firstUpdated() : Uncaught (in promise) TypeError: Cannot read property 'nodeName' of null.
The way I'm using it for testing:
<accordion-panel><li>test</li></accordion-panel>
IDK, it's not working and nothing is printing on the screen. On inspecting the element, I can see there's empty in DOM.
Your problem is that you're trying to use slots, which are a shadow DOM feature but you're not using shadow DOM (since you're overwriting the createRenderRoot method to prevent the creation of the shadowRoot)
So, if you want to use slots, just remove the createRenderRoot function from your class and use shadow DOM
Edit:
You should also update your firstUpdated method so that this part:
const accordionElement = document.getElementById('accordion');
Uses the element from your shadow DOM
const accordionElement = this.shadowRoot.querySelector('.accordion');
Then again, CarbonComponents styling will probably not work so you'll need to add those in some other way

View collections item in Mern

I have some items in a mongodb collection, now i want to view them on a react app, i've that code, but it doesn't display nothing, but if i check value with a console.log() i get the content. How i can do?
import axios from "axios";
const viewMails = []
axios.get('http://localhost:5000/emails').then(res => {
let emailString = JSON.parse(res.request.response)
for (const [index, value] of Array(emailString).entries()) {
viewMails.push(
<div key={index}>
<h1>{value.name}</h1>
<h3>{value.email}</h3>
<p>{value.message}</p>
<p>{value.createdAt}</p>
</div>
);
}
});
export default class EmailsViewer extends Component {
render() {
return (
<div className="emails">
<h1>Sos</h1>
{viewMails}
</div>
);
}
}```
Since you are trying to do a simple component to show a list, if you're using one of the last version of React, consider using axios hook (check the package documentation to see how to add it to your project https://www.npmjs.com/package/axios-hook)
Here I show you an example of what you need to do: list demo

Is it possible to pass "this.state" object from child to parent component using function parameters?

I am quite new to react and working on sending data from child component to parent component by passing function in parent component as a props to child. When I pass string as a function parameter it works fine, but when I pass this.state as a function parameter to parent component it logs empty object.
Here is the code for App.js (Parent) Component
class App extends Component {
onClick = (vals) =>{
console.log(`${"App Components"} ${vals}`)
}
render() {
return (
<div className="App">
<Form fetchValue={(vals) => this.onClick(vals)}>
</Form>
</div>
);
}
}
and here is the function I'm accessing in Form.js (Child) Component as a props whenever "onClickButton" is called
import React, { Component } from 'react'
class Form extends Component {
constructor(props) {
super(props)
this.state = {
user : "Enter User Name",
password: "Enter Your Password",
email: "enter your e-mail"
}
}
onUserValueChnage = (e) => {
this.setState({
user: e.target.value
})
}
onPassValueChnage = (e) => {
this.setState({
password: e.target.value
})
}
onEValueChnage = (e) => {
this.setState({
email: e.target.value
})
}
onClickButton = (e) => {
console.log(this.state)
this.props.on(this.state)
e.preventDefault()
}
render() {
return (
<div>
<form onSubmit={this.onClickButton}>
<input type="text" value={this.state.user} onChange= {this.onUserValueChnage} />
<input type="password" value={this.state.password} onChange={this.onPassValueChnage}/>
<input type="text" value={this.state.email} onChange={this.onEValueChnage}/>
<button>Submit</button>
</form>
</div>
)
}
}
export default Form
I've passed this.state as a parameter to App Component and it logs empty object.
The question I'm trying to ask is, is it possible to pass object as function parameter to parent component?
The issue you're having appears to be as a result of the onClickButton in the child component. You're calling this.props.on. However, the function you're passing in from the parent component's render function is called fetchValue. Instead, in onClickButton in your child component, you should call this.props.fetchValue. I also am performing a spread operation when passing state. It is bad to open up the potential to mutate state directly.
onClickButton = (e) => {
console.log(this.state)
this.props.fetchValue({ ...this.state})
e.preventDefault()
}
Optionally, you can also change your parent component to refer directly to the reference of the function, rather than an anonymous function.
<Form fetchValue={this.onClick} />
Updated Answer:
You'll need to change it to this if you want to see your value. When you do string interpolation and try to print an object, it will output [object, object] because it isn't a string. You'd need to wrap your variable with JSON.stringify(value) if you want it to print the object as a string when doing string interpolation. However, you could also update onClick in your App Component to be something like this, and it should print the object like you're expecting.
onClick = (value) =>{
console.log(value)
}
In your parent:
const onChildClicked = name => console.log(name)
return <Child onClickChild={onChildClicked} />
In Child:
return <div id='hey' onClick={e => props.onChildClicked(e.target)}
Your console should show : hey

How to focus a styled component?

I have a styled component:
const StyledComponent = styled.div`
...
`;
and I want to focus it when the component that uses it is mounted:
class someComponent extends React.Component {
componentDidMount() {
this.sc.focus();
}
render() {
return (
<StyledComponent innerRef={(elem) => { this.sc = elem; }}>
...
</StyledComponent>
);
}
}
this technique does not work - is there a solution for this?
You can't focus non-interactive elements without the use of tabIndex ("tabindex" in normal HTML). The "div" element is considered non-interactive (unlike anchor links "a" and button controls "button".)
If you want to be able to focus this element, you'll need to add a tabIndex prop. You can use .attrs if desired to have it be added automatically so you don't need to write the prop every time.
This link
has an example with both React 16 React.createRef() and the callback method.
Have you tried setting the autoFocus attribute, or is that not fit for your use case?
Try passing the autoFocus prop to your StyledComponent like <StyledComponent autoFocus />.

Resources