diff --git a/packages/sitecore-jss-react/package.json b/packages/sitecore-jss-react/package.json index 43461ba964..be844e52fb 100644 --- a/packages/sitecore-jss-react/package.json +++ b/packages/sitecore-jss-react/package.json @@ -27,7 +27,7 @@ "url": "https://github.com/sitecore/jss/issues" }, "devDependencies": { - "@sitecore-feaas/clientside": "^0.5.5", + "@sitecore-feaas/clientside": "^0.5.6", "@types/chai": "^4.3.4", "@types/chai-string": "^1.4.2", "@types/deep-equal": "^1.0.1", @@ -58,7 +58,7 @@ "typescript": "~4.9.3" }, "peerDependencies": { - "@sitecore-feaas/clientside": "^0.5.5", + "@sitecore-feaas/clientside": "^0.5.6", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/packages/sitecore-jss-react/src/components/BYOCComponent.test.tsx b/packages/sitecore-jss-react/src/components/BYOCComponent.test.tsx index cb08f58e01..9768e8f52e 100644 --- a/packages/sitecore-jss-react/src/components/BYOCComponent.test.tsx +++ b/packages/sitecore-jss-react/src/components/BYOCComponent.test.tsx @@ -31,6 +31,99 @@ describe('BYOCComponent', () => { expect(fooComponent.find('#foo-content')).to.have.length(1); }); + it('should use datasource fields when provided', () => { + const fields = { + prop1: { + value: 'value2', + }, + }; + const mockProps = { + params: { + ComponentName: 'Foo', + }, + fetchedData: {}, + fields, + }; + const Foo = () =>

Test

; + FEAAS.External.registerComponent(Foo, { + name: 'Foo', + properties: { + prop1: { + type: 'string', + }, + }, + }); + const wrapper = mount(); + const fooComponent = wrapper.find('feaas-external'); + expect(fooComponent).to.have.lengthOf(1); + expect(fooComponent.prop('prop1')).to.equal('value2'); + expect(fooComponent.prop('data-external-id')).to.equal('Foo'); + expect(fooComponent.find('#foo-content')).to.have.length(1); + }); + + it('should prefer ComponentProps over datasource fields', () => { + const fields = { + prop1: { + value: 'value2', + }, + }; + const mockProps = { + params: { + ComponentName: 'Foo', + ComponentProps: JSON.stringify({ prop1: 'value1' }), + }, + fetchedData: {}, + fields, + }; + const Foo = () =>

Test

; + FEAAS.External.registerComponent(Foo, { + name: 'Foo', + properties: { + prop1: { + type: 'string', + }, + }, + }); + const wrapper = mount(); + const fooComponent = wrapper.find('feaas-external'); + expect(fooComponent).to.have.lengthOf(1); + expect(fooComponent.prop('prop1')).to.equal('value1'); + expect(fooComponent.prop('data-external-id')).to.equal('Foo'); + expect(fooComponent.find('#foo-content')).to.have.length(1); + }); + + it('should combine ComponentProps and datasource fields', () => { + const fields = { + prop2: { + value: 'value2', + }, + }; + const mockProps = { + params: { + ComponentName: 'Foo', + ComponentProps: JSON.stringify({ prop1: 'value1' }), + }, + fetchedData: {}, + fields, + }; + const Foo = () =>

Test

; + FEAAS.External.registerComponent(Foo, { + name: 'Foo', + properties: { + prop1: { + type: 'string', + }, + }, + }); + const wrapper = mount(); + const fooComponent = wrapper.find('feaas-external'); + expect(fooComponent).to.have.lengthOf(1); + expect(fooComponent.prop('prop1')).to.equal('value1'); + expect(fooComponent.prop('prop2')).to.equal('value2'); + expect(fooComponent.prop('data-external-id')).to.equal('Foo'); + expect(fooComponent.find('#foo-content')).to.have.length(1); + }); + it('should render with static and fetched props when props are prefetched', () => { const fetchedData = { prop2: 'prefetched_value1', @@ -58,7 +151,7 @@ describe('BYOCComponent', () => { const fooComponent = wrapper.find('feaas-external'); expect(fooComponent).to.have.lengthOf(1); expect(fooComponent.prop('prop1')).to.equal('value1'); - expect(fooComponent.prop('datasources')).to.equal('{"prop2":"prefetched_value1"}'); + expect(fooComponent.prop('datasources')).to.equal('{"prop2":"prefetched_value1","_":{}}'); expect(fooComponent.prop('data-external-id')).to.equal('Foo'); expect(fooComponent.find('#foo-content')).to.have.length(1); }); diff --git a/packages/sitecore-jss-react/src/components/BYOCComponent.tsx b/packages/sitecore-jss-react/src/components/BYOCComponent.tsx index d2c66064be..03eb9ad535 100644 --- a/packages/sitecore-jss-react/src/components/BYOCComponent.tsx +++ b/packages/sitecore-jss-react/src/components/BYOCComponent.tsx @@ -135,7 +135,7 @@ export class BYOCComponent extends React.Component { const ErrorComponent = this.props.errorComponent; - let componentProps: { [key: string]: any } = null; + let componentProps: { [key: string]: any } = {}; if (props.params?.ComponentProps) { try { @@ -150,16 +150,16 @@ export class BYOCComponent extends React.Component { ); } - } else { - componentProps = props.fields ? getDataFromFields(props.fields) : {}; } + // apply props from item datasource + const dataSourcesData = { ...props.fetchedData, _: getDataFromFields(props.fields ?? {}) }; // we render fallback on client to avoid problems with client-only components return ( ); diff --git a/packages/sitecore-jss-react/src/components/FEaaSComponent.test.tsx b/packages/sitecore-jss-react/src/components/FEaaSComponent.test.tsx index 00d8e92546..3ffc950027 100644 --- a/packages/sitecore-jss-react/src/components/FEaaSComponent.test.tsx +++ b/packages/sitecore-jss-react/src/components/FEaaSComponent.test.tsx @@ -84,13 +84,12 @@ describe('', () => { }); describe('data', () => { - it('should send override data', () => { + it('should send fetched data', () => { const props: FEaaSComponentProps = { params: { ...requiredParams, - ComponentDataOverride: '{ "foo": "bar", "baz": 1 }', }, - fetchedData: undefined, + fetchedData: { foo: 'bar', baz: 1 }, template: '

', }; const wrapper = shallow(); @@ -123,10 +122,10 @@ describe('', () => { }, }; const template = ` -

- -

- `; +

+ +

+ `; const props: FEaaSComponentProps = { params: { ...requiredParams, @@ -137,58 +136,37 @@ describe('', () => { const wrapper = shallow(); expect(wrapper).to.have.length(1); const output = wrapper.html(); - expect(output).to.contain(`

${fields.sampleText.value}

`); + expect(output).to.contain(`

${fields.sampleText.value}

`); expect(output).to.contain( - `${fields.sampleImage.value.alt}` + `${fields.sampleImage.value.alt}` ); - expect(output).to.contain(`

${fields.sampleNumber.value}

`); + expect(output).to.contain(`

${fields.sampleNumber.value}

`); expect(output).to.contain( - `` + `` ); }); - it('should prefer override data over datasource fields', () => { + it('should combine fetched data with datasource fields', () => { const fields: ComponentFields = { - sampleText: { + fieldText: { value: 'Welcome to Sitecore JSS', }, }; - const override = JSON.stringify({ sampleText: { value: 'Welcome to FEAAS' } }); + const fetched = { customDatasourceId: { fetchedText: 'Welcome to FEAAS' } }; const props: FEaaSComponentProps = { params: { ...requiredParams, - ComponentDataOverride: override, }, + fetchedData: fetched, fields, - template: '

', + template: + '

', }; const wrapper = shallow(); expect(wrapper).to.have.length(1); expect(wrapper.html()).to.contain('Welcome to FEAAS'); - }); - - it('should send prefetched data', () => { - const fetchedData = { - foo: 'bar', - baz: 42, - }; - - const props: FEaaSComponentProps = { - params: { - ...requiredParams, - ComponentDataOverride: '{ "foo": "test", "baz": 22 }', - }, - fetchedData, - template: '

', - }; - - const wrapper = shallow(); - - expect(wrapper).to.have.length(1); - const output = wrapper.html(); - expect(output).to.contain(`

${fetchedData.foo}

`); - expect(output).to.contain(`

${fetchedData.baz}

`); + expect(wrapper.html()).to.contain('Welcome to Sitecore JSS'); }); }); }); diff --git a/packages/sitecore-jss-react/src/components/FEaaSComponent.tsx b/packages/sitecore-jss-react/src/components/FEaaSComponent.tsx index 1d8a9aee1f..2fe52efc34 100644 --- a/packages/sitecore-jss-react/src/components/FEaaSComponent.tsx +++ b/packages/sitecore-jss-react/src/components/FEaaSComponent.tsx @@ -75,21 +75,8 @@ export const FEaaSComponent = (props: FEaaSComponentProps): JSX.Element => { // Missing FEaaS component required props return null; } - - let data: { [key: string]: unknown } = null; - if (props.fetchedData === null || props.fetchedData === undefined) { - if (props.params?.ComponentDataOverride) { - // Use override data if provided - try { - data = JSON.parse(props.params.ComponentDataOverride); - } catch (e) { - data = null; - } - } else if (props.fields) { - // Otherwise use datasource data (provided in fields) - data = getDataFromFields(props.fields); - } - } + // combine fetchedData from server with datasource data (if present) + const data = { ...props.fetchedData, _: getDataFromFields(props.fields ?? {}) }; // FEaaS control would still be hydrated by client // we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side @@ -97,7 +84,7 @@ export const FEaaSComponent = (props: FEaaSComponentProps): JSX.Element => { // FEAAS should not fetch anything, since JSS does the fetching - so we pass empty array into fetch param return ( =16.8.0" - checksum: 108ed61488f7f5777d3ae846f6d1c188a245440a511b7bc06200f4b236cf5e140075646efa4e3a1070ce7737fb4a2a808383e65d6570bd7c6a540dc183cc6e29 + checksum: 6346d7cac5dc295ddf377fd802404229256fdfb4e2cabdf0cbd0ae8350a2fafe7e2b49abe31025a9dec848f4545e96178ec2173369a328799845ed6253c4cb90 languageName: node linkType: hard @@ -7143,7 +7143,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sitecore-jss/sitecore-jss-react@workspace:packages/sitecore-jss-react" dependencies: - "@sitecore-feaas/clientside": ^0.5.5 + "@sitecore-feaas/clientside": ^0.5.6 "@sitecore-jss/sitecore-jss": 21.7.0-canary.33 "@types/chai": ^4.3.4 "@types/chai-string": ^1.4.2 @@ -7177,7 +7177,7 @@ __metadata: ts-node: ^10.9.1 typescript: ~4.9.3 peerDependencies: - "@sitecore-feaas/clientside": ^0.5.5 + "@sitecore-feaas/clientside": ^0.5.6 react: ^18.2.0 react-dom: ^18.2.0 languageName: unknown