Skip to content

Commit

Permalink
feat: poc for useEffect to manage state dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
alharris-at committed Feb 25, 2022
1 parent 24c9eac commit ce65105
Show file tree
Hide file tree
Showing 9 changed files with 779 additions and 217 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ describe('amplify render tests', () => {
script: ScriptKind.JS,
}).componentText,
).toMatchSnapshot();
it('supports all initial value binding types', () => {
expect(generateWithAmplifyRenderer('workflow/initialValueBindings')).toMatchSnapshot();
});
});

Expand Down
3 changes: 3 additions & 0 deletions packages/codegen-ui-react/lib/imports/import-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
limitations under the License.
*/
export enum ImportSource {
REACT = 'react',
UI_REACT = '@aws-amplify/ui-react',
UI_REACT_INTERNAL = '@aws-amplify/ui-react/internal',
AMPLIFY_DATASTORE = '@aws-amplify/datastore',
Expand All @@ -38,6 +39,7 @@ export enum ImportValue {
USE_DATA_STORE_DELETE_ACTION = 'useDataStoreDeleteAction',
USE_AUTH_SIGN_OUT_ACTION = 'useAuthSignOutAction',
USE_STATE_MUTATION_ACTION = 'useStateMutationAction',
USE_EFFECT = 'useEffect',
}

export const ImportMapping: Record<ImportValue, ImportSource> = {
Expand All @@ -58,4 +60,5 @@ export const ImportMapping: Record<ImportValue, ImportSource> = {
[ImportValue.USE_DATA_STORE_DELETE_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_AUTH_SIGN_OUT_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_STATE_MUTATION_ACTION]: ImportSource.UI_REACT_INTERNAL,
[ImportValue.USE_EFFECT]: ImportSource.REACT,
};
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
buildUseActionStatement,
mapSyntheticStateReferences,
buildStateStatements,
buildUseEffectStatements,
} from './workflow';

export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer<
Expand Down Expand Up @@ -605,6 +606,12 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer
statements.push(entry);
});

const useEffectStatements = buildUseEffectStatements(component, this.componentMetadata);
useEffectStatements.forEach((entry) => {
this.importCollection.addMappedImport(ImportValue.USE_EFFECT);
statements.push(entry);
});

return statements;
}

Expand Down
38 changes: 38 additions & 0 deletions packages/codegen-ui-react/lib/workflow/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
StudioComponentProperty,
ComponentMetadata,
getComponentFromComponentTree,
computeStateReferenceMetadata,
} from '@aws-amplify/codegen-ui';
import {
isStateProperty,
Expand Down Expand Up @@ -63,6 +64,43 @@ const PrimitiveDefaultValuePropMapping: PrimitiveLevelPropConfiguration<string>
},
);

/**
* TODO: Determine if we should be initializing state values w/ these data deps to `undefined`,
* then only setting the value here in the useEffect once the dependencies are no longer null.
*
* This way we'll be able to still use the useEffect for an initialization once the data values have settled,
* and we won't overwrite whatever mutation applies to them if useAuth or useData changes.
*/
export function buildUseEffectStatements(
component: StudioComponent,
componentMetadata: ComponentMetadata,
): Statement[] {
const stateReferenceMetadata = computeStateReferenceMetadata(component, componentMetadata.stateReferences);
return stateReferenceMetadata
.filter(({ dataDependencies }) => dataDependencies.length > 0)
.map(({ stateReference, dataDependencies }) => {
return factory.createExpressionStatement(
factory.createCallExpression(factory.createIdentifier('useEffect'), undefined, [
factory.createArrowFunction(
undefined,
undefined,
[],
undefined,
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
factory.createBlock([
factory.createExpressionStatement(
factory.createCallExpression(factory.createIdentifier(getSetStateName(stateReference)), undefined, [
getStateInitialValue(component, componentMetadata, stateReference),
]),
),
]),
),
factory.createArrayLiteralExpression(dataDependencies.map(factory.createIdentifier), false),
]),
);
});
}

export function mapSyntheticStateReferences(componentMetadata: ComponentMetadata) {
return componentMetadata.stateReferences.map((stateReference) => {
const { componentName, property } = stateReference;
Expand Down
Loading

0 comments on commit ce65105

Please sign in to comment.