Skip to content

Commit 6bb55b1

Browse files
committed
ref(ui): Improve member loading in actor avatar
Right now if the member isn't present in the store when the avatar renders we'll never end up showing the users avatar
1 parent d57dd04 commit 6bb55b1

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

static/app/components/avatar/actorAvatar.spec.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,31 @@ describe('ActorAvatar', function () {
9696
expect(await screen.findByText('CT')).toBeInTheDocument();
9797
expect(mockRequest).toHaveBeenCalled();
9898
});
99+
100+
it.only('should fetch a user not in the store', function () {
101+
const organization = OrganizationFixture();
102+
103+
OrganizationStore.onUpdate(organization, {replace: true});
104+
105+
const user2 = UserFixture({id: '2', name: 'COOL USER'});
106+
107+
const mockRequest = MockApiClient.addMockResponse({
108+
url: `/organizations/${organization.slug}/members/`,
109+
method: 'GET',
110+
body: [user],
111+
});
112+
113+
render(
114+
<ActorAvatar
115+
actor={{
116+
id: user2.id,
117+
name: user2.name,
118+
email: user2.email,
119+
type: 'user',
120+
}}
121+
/>
122+
);
123+
124+
screen.debug();
125+
});
99126
});

static/app/components/avatar/actorAvatar.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import * as Sentry from '@sentry/react';
22

33
import TeamAvatar from 'sentry/components/avatar/teamAvatar';
44
import UserAvatar from 'sentry/components/avatar/userAvatar';
5-
import LoadingIndicator from 'sentry/components/loadingIndicator';
6-
import MemberListStore from 'sentry/stores/memberListStore';
75
import type {Actor} from 'sentry/types';
6+
import {useMembers} from 'sentry/utils/useMembers';
87
import {useTeamsById} from 'sentry/utils/useTeamsById';
98

9+
import Placeholder from '../placeholder';
10+
1011
import type {BaseAvatarProps} from './baseAvatar';
1112

1213
interface Props extends BaseAvatarProps {
@@ -24,12 +25,33 @@ function LoadTeamAvatar({
2425
const team = teams.find(t => t.id === teamId);
2526

2627
if (isLoading) {
27-
return <LoadingIndicator mini />;
28+
const size = `${props.size}px`;
29+
return <Placeholder width={size} height={size} />;
2830
}
2931

3032
return <TeamAvatar team={team} {...props} />;
3133
}
3234

35+
/**
36+
* Wrapper to assist loading the user from api or store
37+
*/
38+
function LoadMemberAvatar({
39+
userId,
40+
...props
41+
}: {userId: string} & Omit<React.ComponentProps<typeof UserAvatar>, 'team'>) {
42+
debugger;
43+
44+
const {members, fetching} = useMembers({ids: [userId]});
45+
const user = members.find(u => u.id === userId);
46+
47+
if (fetching) {
48+
const size = `${props.size}px`;
49+
return <Placeholder shape="circle" width={size} height={size} />;
50+
}
51+
52+
return <UserAvatar user={user} {...props} />;
53+
}
54+
3355
function ActorAvatar({size = 24, hasTooltip = true, actor, ...props}: Props) {
3456
const otherProps = {
3557
size,
@@ -38,8 +60,7 @@ function ActorAvatar({size = 24, hasTooltip = true, actor, ...props}: Props) {
3860
};
3961

4062
if (actor.type === 'user') {
41-
const user = actor.id ? MemberListStore.getById(actor.id) ?? actor : actor;
42-
return <UserAvatar user={user} {...otherProps} />;
63+
return <LoadMemberAvatar userId={actor.id} {...otherProps} />;
4364
}
4465

4566
if (actor.type === 'team') {

0 commit comments

Comments
 (0)