Я использую веб-компоненты с освещенным элементом внутри приложения React.
Когда я обновляю атрибут веб-компонента из компонента React с помощью JSON Stringified объекта, веб-компонент не обновляется, пока я не принудительно заставлю обновление метода веб-компонента attributeChangedCallback
.
Реагирующий компонент
const AppHeader: React.SFC<AppHeaderProps> = () => {
return (
<userContext.Consumer>
{({ user }) => {
const userName: string = (user as UserType)?.given_name || '';
const greetings = userName ? `Hello ${userName}!` : '';
return (
<app-header>
<h1 slot="title">React all-in-one starter</h1>
<div style={rightSideStyles} slot="right-side">
<p className="username">{greetings}</p>
<app-login user={JSON.stringify(user)} />
</div>
</app-header>
);
}}
</userContext.Consumer>
);
};
компонент входа в приложение , принудительно запрашивающий обновление attributeChangedCallback
method.
@customElement('app-login')
export class AppLogin extends LitElement {
@property({
type: Object,
})
user: UserType | null = null;
loginSuccessEventKey: string = 'login-success';
loginFailureEventKey: string = 'login-failure';
logoutSuccessEventKey: string = 'logout-success';
logoutFailureEventKey: string = 'logout-failure';
handleClickGetAuth() {
const token = jwt.sign(userData, process.env.REACT_APP_JWT_SECRET as Secret);
localStorage.setItem('token', token);
const loginSuccessEvent = new CustomEvent(this.loginSuccessEventKey, { composed: true, bubbles: true });
this.dispatchEvent(loginSuccessEvent);
}
handleClickLogout() {
localStorage.removeItem('token');
const logoutSuccessEvent = new CustomEvent(this.logoutSuccessEventKey, {
composed: true,
bubbles: true,
});
this.dispatchEvent(logoutSuccessEvent);
}
attributeChangedCallback(name: any, oldVal: any, newVal: any) {
super.attributeChangedCallback(name, oldVal, newVal);
this.requestUpdate();
}
render() {
const logoutButton = html`
<app-button primary color="red" @click="${this.handleClickLogout}">Salir</app-button>
`;
const loginButton = html`
<app-button primary color="blue" @click="${this.handleClickGetAuth}">Acceder</app-button>
`;
return html`
<div>
${isObjectEmpty(this.user) ? loginButton : logoutButton}
</div>
`;
}
}
Чтобы установить здесь немного больше контекста, после события login-success
приложение, которое упаковывает AppHeader
, обновляет состояние приложения, помещая его в контекст userContext
.
Почему это? Если attributeChangedCallback
срабатывает, это потому, что он обнаруживает изменение атрибута, но запускается любое событие свойства, например hasChanged
(в том же определении свойства) или updated
.