-
Notifications
You must be signed in to change notification settings - Fork 12
refactor: refactor the infinite scroll wrapper and queries #267
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for reearth-web ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
Codecov Report
@@ Coverage Diff @@
## main #267 +/- ##
=======================================
Coverage 52.19% 52.19%
=======================================
Files 56 56
Lines 1205 1205
Branches 193 193
=======================================
Hits 629 629
Misses 503 503
Partials 73 73
|
if (ref.current && ref.current?.scrollHeight <= document.documentElement.clientHeight) { | ||
onLoadMore?.(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think something about this isn't quite working correctly. In the Asset settings page you get this called when the page loads, before any scrolling. It isn't a BIG deal, since it only seems to call once, but it really shouldn't call UNLESS the page is too long for the initial fetch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just happen to see this. I think this part comes from my suggestion some weeks ago. This is only for solving large screen issue (first fetch cannot fill the area) and yes it should be called only under this situation but the point is it seems to be some difficult to check if it is too long (from my memory it was due to the DOM structure is different with different usecases and the function is a common util at that time). So my idea was always want the content fill the area and if not and if there's more data then load more. At that time i only look into this with load projects in large screen issue and i'm not sure about other situations (like Asset page). And also i think the code changes a lot now maybe can optimize this with adding an area's ref?
const assets = data?.assets.edges | ||
.map<Asset | undefined>(asset => | ||
asset.node | ||
? { | ||
id: asset.node.id, | ||
name: asset.node.name, | ||
size: asset.node.size, | ||
teamId: asset.node.teamId, | ||
url: asset.node.url, | ||
contentType: asset.node.contentType, | ||
} | ||
: undefined, | ||
) | ||
.filter((asset): asset is Asset => !!asset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can keep it more concise if you do something like this:
const assets = data?.assets.edges
.map<Asset | undefined>(({ node })=> node)
.filter((asset): asset is Asset => !!asset);
Please test to make sure it works though.
Also, what is the purpose of the filter? Is there any chance that there'll be an undefined asset inside the assets array?
const projects = useMemo(() => { | ||
return (projectNodes ?? []) | ||
return (projectData?.projects.edges ?? []) | ||
.map<Project | undefined>(project => | ||
project | ||
project.node | ||
? { | ||
id: project.id, | ||
description: project.description, | ||
name: project.name, | ||
image: project.imageUrl, | ||
status: toPublishmentStatus(project.publishmentStatus), | ||
isArchived: project.isArchived, | ||
sceneId: project.scene?.id, | ||
id: project.node.id, | ||
description: project.node.description, | ||
name: project.node.name, | ||
image: project.node.imageUrl, | ||
status: toPublishmentStatus(project.node.publishmentStatus), | ||
isArchived: project.node.isArchived, | ||
sceneId: project.node.scene?.id, | ||
} | ||
: undefined, | ||
) | ||
.filter((project): project is Project => !!project); | ||
}, [projectNodes]); | ||
}, [projectData?.projects.edges]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the comment above, you can destructure the node so you can clean up the assignment below, something like this:
const projects = useMemo(() => {
return (projectData?.projects.edges ?? [])
.map<Project | undefined>(({node})=>
node
? {
id: node.id,
description: node.description,
name: node.name,
image: node.imageUrl,
status: toPublishmentStatus(node.publishmentStatus),
isArchived: node.isArchived,
sceneId: node.scene?.id,
}
: undefined,
)
.filter((project): project is Project => !!project);
}, [projectData?.projects.edges]);
You can also destructure further like this:
(projectData?.projects.edges ?? [])
.map<Project | undefined>(({node: { id, description, name, imageUrl: image, publishmentStatus: status, isArchived, scene: {id?: sceneId}}})=> {
id,
description,
name,
etc,
etc,
}
The second one might be too much? Also, you can go even further to ONLLY destructure specifically the keys that are different between the data and the frontend's Project (aka image VS imageUrl, etc) and leave the rest as ...rest
. But again, it might be too much and the code might become harder to understand. I'll let you play around and find whats best here
const datasetSchemas = data?.datasetSchemas.edges | ||
.map<Item | undefined>(item => | ||
item.node ? { id: item.node.id, name: item.node.name } : undefined, | ||
) | ||
.filter((item): item is Item => !!item); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: destructure the node and then you don't need to assign the values to keys. And again, not sure if the filter is necessary? Let me know
const project = useMemo( | ||
() => | ||
rawProject?.id | ||
rawProject?.node?.id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Destructure node
.map<Project | undefined>(project => | ||
project | ||
project.node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Destructure node
const wrapperRef = useRef<HTMLDivElement>(null); | ||
const { handleAutoFillPage, handleScrollToBottom } = useHooks(onGetMoreItems); | ||
|
||
useEffect(() => { | ||
if (wrapperRef.current && !loading && hasMoreItems) handleAutoFillPage(wrapperRef); | ||
}, [handleAutoFillPage, hasMoreItems, loading, onGetMoreItems]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This component doesn't have too many hooks, so you don't really need the hooks.ts file. But if you want to keep the file, please bring the ref and useEffect into the hooks file as well to keep things consistent (unless there is a reason you separated them, in which case please let me know).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good! A few clean up comments but really good refactor!
@@ -42,26 +42,27 @@ export default ({ projectId }: Params) => { | |||
}); | |||
|
|||
const rawProject = useMemo( | |||
() => data?.projects.nodes.find(p => p?.id === projectId), | |||
() => data?.projects.edges.find(p => p.node?.id === projectId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't need rawProject's other fields (I forget what comes along with node
...) you can destructure one step further to the node.
Then, below you can simplify like the other comments.
Overview
The changes:
1- Refactoring the queries of graphql and remove nodes
2- Modify all the queries on hooks
3- Create (infinite scroll) wrapper atom and reuse it wherever the need for infinite scroll
What I've done
The pages affected by this changes :
1- Dashboard page
2- setting pages :
1- Project list page
2- Assets page
3- Datasets page
4- setting page for each page
5- accessing pages from reearth-editor
What I haven't done
How I tested
Screenshot
Which point I want you to review particularly
Memo