Skip to content

Conversation

@mocca102
Copy link
Contributor

  • Track recommendation click
  • Track recommendation view

@mocca102 mocca102 requested a review from a team November 22, 2023 18:48
@mocca102 mocca102 force-pushed the csl-3047-os-ui-autocomplete-implement-recommendation-tracking branch from 9149817 to e6e2b51 Compare November 29, 2023 21:44
Copy link
Contributor

@esezen esezen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! Thanks for making the changes.

I left some small comments, let me know what you think

Lets also get a review from the Professor @deomsj

@esezen esezen requested a review from deomsj December 5, 2023 15:23
Copy link
Contributor

@deomsj deomsj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work on this @mocca102 and @esezen!!!

I've left a number of ideas, questions, and suggestions as inline comments in this review. Looking forward to hearing your thoughts on these points and having another look at this together on a pairing call or async for another round of review.

I appreciate all of your great work on this & I'll follow your lead on how I can best support with next steps :)

.map((section) => section.ref);

useEffect(() => {
const observer = new IntersectionObserver(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused. What do we mean by "intersection" here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import ConstructorIO from '@constructor-io/constructorio-client-javascript';
import { Section } from '../types';

function useRecommendationsObserver(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some brief comment above this function definition describing the scope of responsibility for this hook? We are using some very cool patterns in here that will not be obvious to many developers. I'd love to see explicit documentation for what this hook is doing for us and what needs to be configured elsewhere in the lib code or in a lib consumer's src code in order for this to behave as it is intended

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES. Well done sir. I found these explanations to be very, very helpful :)

useEffect(() => {
setActiveSections(zeroStateActiveSections ? zeroStateSections : sections);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [zeroStateActiveSections]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something, but this looks like derived state at this point.
Can we simplify?

all of this:

  // Define All Sections
  const [activeSections, setActiveSections] = useState<UserDefinedSection[]>(
    zeroStateActiveSections ? zeroStateSections : sections
  );

  useEffect(() => {
    setActiveSections(zeroStateActiveSections ? zeroStateSections : sections);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [zeroStateActiveSections]);

to just, this:
this:

  const activeSections = zeroStateActiveSections ? zeroStateSections : sections;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I wanted to make it reactive to only zeroStateActiveSections so it updates the state only if zeroStateActiveSections changes. But whenever zeroStateActiveSections, zeroStateSections and sections also change and they're passed as props to the hook so the whole hook rerun every time any way.

TLDR; I thought this was an optimization but I don't think it is anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

);
}, [autocompleteResults, recommendationsResults, activeSections]);

// Reset sections
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this effect? I'm wondering why we need to manage activeSections as its own state here at all instead of deriving it from other state passed in to this hook...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

src/utils.ts Outdated

if (sectionConfig.type === 'recommendations') {
// If user provided a ref in config, use it. Otherwise, use the ref from our refs array
section.ref = sectionConfig.ref || sectionsRefs.current[index];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • when would this value arrive to this point via sectionConfig.ref?
  • when would this value arrive to this point via sectionsRefs.current[index]

can we add comments or use some precisely named consts here to make this explicit to anyone referencing or building on top of this code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@deomsj deomsj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done @mocca102!

I haven't tried breaking functionality locally yet, but I'm lovin the changes made here from a code clarity / maintainability perspective.

I left a couple more questions & ideas. Holla for pairing sesh or for another review as you like :)

* Custom hook that observes the visibility of recommendation sections and calls trackRecommendationView event.
* This is done by using the IntersectionObserver API to observe the visibility of each recommendation section.
* That is done by passing the ref of each recommendation section to the IntersectionObserver.
* The refs are either passed by the user in section config or generated by the library by default.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vocab alignment:

  • "user" - end user who's browser this production code is rendered on
  • "lib consumer" - developer / team who is consuming this library and building on top of it

src/utils.ts Outdated
data: sectionData,
};

// If user provided a ref in `sectionConfig`, use it. Otherwise, use the ref from our library generated refs array
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Four questions:

  1. how will the lib consumer know that they can pass these refs?
  2. how will lib consumer know how to pass this ref?
  3. what happens if they don't pass this ref and are using the lib's component interface?
  4. what happens if they don't pass this ref and are using the lib's hook interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It's a prop on type SectionConfiguration https://github.com/Constructor-io/constructorio-ui-autocomplete/pull/107/files/55c168e54f3bc1568827cba615592e193f2fc3c1#diff-c54113cf61ec99691748a3890bfbeb00e10efb3f0a76f03a0fd9ec49072e410aR83
  2. same as 1 but we can add more documentation explaining that
  3. and 4. There's no change between hooks and component interface as long as they use getSectionProps

We need to add docs for getSectionProps

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great callout. This would have made things more clear if added from the beginning. Added here
06ced4f#diff-8fa4b52909f895e8cda060d2035234e0a42ca2c7d3f8f8de1b35a056537bf199R40 @deomsj

@mocca102 mocca102 requested a review from deomsj December 13, 2023 01:06
Copy link
Contributor

@deomsj deomsj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings from dev build on my machine:

  • all storybook tests are passing!
  • all rec view and rec click events look great! (screenshot below for more detail)
  • tried a handfull of stories without recs and both UX and network traffic continue to behave as expected!

Excellent work on this, @mocca102!!!

Screenshot 2023-12-13 at 9 25 47 AM

@esezen esezen merged commit fb0eb56 into main Dec 15, 2023
@esezen esezen deleted the csl-3047-os-ui-autocomplete-implement-recommendation-tracking branch December 15, 2023 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants