Skip to content

Commit

Permalink
refactor(UNI-221): refactored to use hoc to simplify component code
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff-Tian committed Apr 26, 2024
1 parent 30c1420 commit 73937cd
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/components/BlogList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {fallbackThumbnail} from "@/common/constants";
import Taro from "@tarojs/taro";
import {useEffect, useState} from "react";
import {gql, useQuery} from "@apollo/client";
import {ErrorDisplay} from "@/components/ErrorDisplay";
import {ErrorDisplay} from "@/components/errors/ErrorDisplay";
import useComponentRefresh from "@/hooks/use-component-refresh";

export const YUQUE_BLOG = gql`
Expand Down
2 changes: 1 addition & 1 deletion src/components/brickverse/banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Swiper, SwiperItem, View} from "@tarojs/components";
import {useContext, useEffect} from "react";
import {RefreshContext} from "@/contexts/refresh-context";
import {GET_POSTS_QUERY} from "@/api/brickverse";
import {ErrorDisplay} from "@/components/ErrorDisplay";
import {ErrorDisplay} from "@/components/errors/ErrorDisplay";
import {useQuery} from "@apollo/client";
import Taro from "@tarojs/taro";
import './brickverse.styl';
Expand Down
File renamed without changes.
35 changes: 35 additions & 0 deletions src/components/errors/error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";

interface ErrorBoundaryProps {
fallback: React.ReactElement;
}

interface ErrorBoundaryState {
hasError: boolean;
}

export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) {
super(props);

this.state = {hasError: false};
}

static getDerivedStateFromError(_: Error): ErrorBoundaryState {
// 更新 state 使得下一次渲染能够显示降级后的 UI
return {hasError: true}
}

componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
// 你同样可以将错误日志上报给服务器
console.error('Uncaught error:', error, errorInfo);
}

render() {
if (this.state.hasError) {
return this.props.fallback;
}

return this.props.children;
}
}
32 changes: 7 additions & 25 deletions src/components/github/calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,16 @@
import {View} from "@tarojs/components";
import CalendarHeatMap from "@/components/calendar-heat-map";
import {useQuery} from "@apollo/client";
import {ErrorDisplay} from "@/components/ErrorDisplay";
import withGraphqlQuery from "@/components/higher-orders/with-graphql-query";
import {GITHUB_STATS} from "@/api/github";


const GitHubCalendar = () => {
const {loading, error, data} = useQuery(GITHUB_STATS)

if (error) {
return <ErrorDisplay error={error}>发生了错误!</ErrorDisplay>
}

if (loading) {
return <View>
<CalendarHeatMap data={[]} showMonthLabel showWeekLabel theme='github' />
</View>
}

const contributions = data.viewer.contributionsCollection.contributionCalendar.weeks.map(week => week.contributionDays.map(day => ({
const GitHubCalendar = ({data}) => {
const contributions = data?.viewer?.contributionsCollection?.contributionCalendar?.weeks?.map(week =>
week.contributionDays.map(day => ({
date: day.date,
count: day.contributionCount
}))
).flat();
).flat() ?? [];

return (
<View>
<CalendarHeatMap data={contributions} showMonthLabel showWeekLabel theme='github' />
</View>
)
return <CalendarHeatMap data={contributions} showMonthLabel showWeekLabel theme='github' />
}

export default GitHubCalendar
export default withGraphqlQuery(GitHubCalendar, GITHUB_STATS);
2 changes: 1 addition & 1 deletion src/components/github/timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {AtTimeline} from "taro-ui";
import {GITHUB_TIMELINE} from "@/api/github";
import {Item} from "taro-ui/types/timeline";
import {useQuery} from "@apollo/client";
import {ErrorDisplay} from "../ErrorDisplay";
import {ErrorDisplay} from "../errors/ErrorDisplay";

const GitHubTimeline = () => {
const {loading, data, error, refetch} = useQuery(GITHUB_TIMELINE)
Expand Down
50 changes: 50 additions & 0 deletions src/components/higher-orders/with-graphql-query.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {DocumentNode, useQuery} from "@apollo/client";
import useComponentRefresh from "@/hooks/use-component-refresh";
import {ErrorDisplay} from "@/components/errors/ErrorDisplay";
import React from "react";
import ErrorBoundary from "@/components/errors/error-boundary";

interface WithGraphqlQueryProps<TData> {
data: TData | null | undefined;
}

interface HOCProps<TData> extends Omit<WithGraphqlQueryProps<TData>, 'data'> {
query: DocumentNode;
LoadingComponent?: React.ComponentType;
ErrorComponent?: React.ComponentType<{ error: Error, refetch: () => void }>;
}

const DefaultLoadingComponent: React.FC = () => <div>loading...</div>;
const DefaultErrorComponent: React.FC<{ error: Error, refetch: () => void }> = ({error, refetch}) => (
<ErrorDisplay error={error} refetch={refetch}>发生了错误!</ErrorDisplay>);

/**
* A higher order component that wraps a component with a graphql query.
* The component to wrap, all it needs to do is handle the data prop. error and such are handled by this HOC.
* @param WrappedComponent
* @param query
*/
function withGraphqlQuery<TData = any>(WrappedComponent: React.ComponentType<WithGraphqlQueryProps<TData>>, query: DocumentNode) {
const HOC: React.FC<HOCProps<TData>> = ({LoadingComponent, ErrorComponent, ...rest}) => {
const {loading, data, error, refetch} = useQuery<TData>(query);
useComponentRefresh(refetch);

if (error) {
const ErrorComponentToRender = ErrorComponent || DefaultErrorComponent;
return <ErrorComponentToRender error={error} refetch={refetch} />
}

if (loading || !data) {
const LoadingComponentToRender = LoadingComponent || DefaultLoadingComponent;
return <ErrorBoundary fallback={<LoadingComponentToRender />}>
<WrappedComponent data={undefined} {...rest} />
</ErrorBoundary>
}

return <WrappedComponent data={data} {...rest} />
}

return HOC;
}

export default withGraphqlQuery;
2 changes: 1 addition & 1 deletion src/pages/subpages/about/github.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {View} from "@tarojs/components";
import {useQuery} from "@apollo/client";
import {ErrorDisplay} from "@/components/ErrorDisplay";
import {ErrorDisplay} from "@/components/errors/ErrorDisplay";
import useComponentRefresh from "@/hooks/use-component-refresh";
import {GITHUB_STATS} from "@/api/github";
import GitHubCalendar from "@/components/github/calendar";
Expand Down
2 changes: 1 addition & 1 deletion src/pages/subpages/brickverse/post.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {GET_POST_QUERY} from "@/api/brickverse";
import {useQuery} from "@apollo/client";
import Taro from "@tarojs/taro";
import {ErrorDisplay} from "@/components/ErrorDisplay";
import {ErrorDisplay} from "@/components/errors/ErrorDisplay";
import {View} from "@tarojs/components";
import {useContext} from "react";
import {AppContext, AppNameEnum} from "@/contexts/app-context";
Expand Down

1 comment on commit 73937cd

@vercel
Copy link

@vercel vercel bot commented on 73937cd Apr 26, 2024

Choose a reason for hiding this comment

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

Please sign in to comment.