Skip to content

fix: only provide first context if multiple SM factories of same type #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineState } from '@lwc/state';

export default defineState((atom) => (initialName = 'anotherFoo') => ({
name: atom(initialName),
}));
3 changes: 3 additions & 0 deletions example/src/modules/x/childState/childState.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { defineState } from '@lwc/state';
import parentStateFactory from 'x/parentState';
import anotherParentStateFactory from 'x/anotherParentState';

export default defineState((atom, _computed, update, fromContext) => (initialName = 'bar') => {
const name = atom(initialName);
const parentState = fromContext(parentStateFactory);
const anotherParentState = fromContext(anotherParentStateFactory);

const updateName = update({ name }, (_, newName) => ({
name: newName,
Expand All @@ -13,5 +15,6 @@ export default defineState((atom, _computed, update, fromContext) => (initialNam
name,
updateName,
parentState,
anotherParentState,
};
});
1 change: 1 addition & 0 deletions example/src/modules/x/contextChild/contextChild.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<h3>Child</h3>
<p class='child-content'>nameProvidedByParent: {nameProvidedByParent}</p>
<p class='another-child-content'>AnotherNameProvidedByParent: {anotherNameProvidedByParent}</p>
<x-context-grand-child></x-context-grand-child>
</template>
4 changes: 4 additions & 0 deletions example/src/modules/x/contextChild/contextChild.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ export default class ContextChild extends ContextfulLightningElement {
get nameProvidedByParent() {
return this.childState.value.parentState.value?.name ?? 'not available';
}

get anotherNameProvidedByParent() {
return this.childState.value.anotherParentState.value?.name ?? 'not available';
}
}
6 changes: 6 additions & 0 deletions example/src/modules/x/contextParent/contextParent.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { api } from 'lwc';
import { ContextfulLightningElement } from '@lwc/state/context';
import parentStateFactory from 'x/parentState';
import anotherParentStateFactory from 'x/anotherParentState';

export default class ContextParent extends ContextfulLightningElement {
@api
parentState = parentStateFactory('parentFoo');

@api
dupParentState;

anotherParentState = anotherParentStateFactory();

@api
hideChild = false;

Expand Down
25 changes: 24 additions & 1 deletion example/src/modules/x/contextRoot/context.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, querySelectorDeep, clientSideRender } from '@lwc/test-runner';
import { expect, querySelectorDeep, clientSideRender, sinon } from '@lwc/test-runner';
import parentStateFactory from '../parentState/parentState.js';

const componentPath = import.meta.resolve('./contextRoot.js');

Expand Down Expand Up @@ -97,6 +98,28 @@ describe('context', () => {
expect(contextParent.parentState.subscribers.size).toBe(1);
});

it('can provide multiple context of different varieties', async () => {
await clientSideRender(parentEl, componentPath, {});
const childContent = querySelectorDeep('.child-content');
const anotherChildContent = querySelectorDeep('.another-child-content');

expect(childContent.innerText).to.include('parentFoo');
expect(anotherChildContent.innerText).to.include('anotherFoo');
});

it('logs an error when multiple contexts of same variety are provided', async () => {
const errorSpy = sinon.spy(console, 'error');
// context parent already has a state manager of type parentStateFactory
await clientSideRender(parentEl, componentPath, {
dupParentState: parentStateFactory(),
});

expect(errorSpy.callCount).to.equal(1);
expect(errorSpy).to.have.been.calledWith(
'Multiple contexts of the same variety were provided. Only the first context will be used.',
);
});

it('children can access context directly with detached fromContext', async () => {
const el = await clientSideRender(parentEl, componentPath, {});
const childWithDetachedFromContext = querySelectorDeep('.child-content-detached', el);
Expand Down
2 changes: 1 addition & 1 deletion example/src/modules/x/contextRoot/contextRoot.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<x-context-parent></x-context-parent>
<x-context-parent dup-parent-state={dupParentState}></x-context-parent>
<x-context-lonely-child></x-context-lonely-child>
<x-context-parent-detached></x-context-parent-detached>
</template>
7 changes: 5 additions & 2 deletions example/src/modules/x/contextRoot/contextRoot.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { LightningElement } from 'lwc';
import { LightningElement, api } from 'lwc';

export default class ContextRoot extends LightningElement {}
export default class ContextRoot extends LightningElement {
@api
dupParentState;
}
Loading
Loading