Skip to content

feat: Return default value whenever query function returns undefined.#57

Merged
aboodman merged 4 commits intomainfrom
aa/default
Nov 12, 2023
Merged

feat: Return default value whenever query function returns undefined.#57
aboodman merged 4 commits intomainfrom
aa/default

Conversation

@aboodman
Copy link
Copy Markdown
Contributor

@aboodman aboodman commented Nov 8, 2023

feat: Return default value whenever query function returns undefined.

@aboodman aboodman requested a review from arv November 8, 2023 07:45
@aboodman aboodman marked this pull request as draft November 8, 2023 08:00
@aboodman aboodman marked this pull request as ready for review November 9, 2023 03:10
Comment thread src/index.ts Outdated
r: Subscribable<Tx, D> | null | undefined,
query: (tx: Tx) => Promise<R>,
def: R,
export function useSubscribe<Tx, Data, Default>(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just renaming template params to improve readability.

Comment thread src/index.test.tsx Outdated
render(<A rep={rep} />, div);
await sleep(1);
expect(renderLog).to.deep.equal(['render A', null, 'render B', null, null]);
expect(renderLog).to.deep.equal([
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have looked at this pretty hard and I am sure that this expectation is actually correct.

The subscription returns the default, then the query runs and re-fires the subscription, which re-renders.

I cannot explain why my change made it faster-enough to fit under the 1ms but somehow it does.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this is right :-)

With the new code it renders twice. That is not needed. Nothing changed.

The subscribe body returns the same value as the default value so that should not trigger a render.

OK so I still think the implementation of `useSubscribe` is fine.
What was happening with the test was that `setState` *does* skip
re-renders if the value is identical via Object.is().

When I changed the semantics of useSubscribe() I didn't change
some of the test code to match. Previously the test code was
manually coallescing undefined to null. Because the snapshot
state inside useSubscribe now starts out as undefined rather
than `def` this meant that when the query returned, it caused a
re-render.
Comment thread src/index.ts
): R {
const [snapshot, setSnapshot] = useState<R>(def);
) {
const [snapshot, setSnapshot] = useState<QueryRet | undefined>(undefined);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I find it easier to reason about this by setting the state to def here.

But both should behave the same so your call here.

Comment thread src/index.ts
deps: Array<unknown> = [],
): R {
const [snapshot, setSnapshot] = useState<R>(def);
) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please write out the return type here. The inferred type is pretty cryptic.

export type RemoveUndefined<T> = T extends undefined ? never : T;
...
): Default | RemoveUndefined<QueryRet> {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants