feat(apps.web#components): added "swr", and ErrorBoundary component

Signed-off-by: GitHub <noreply@github.com>
This commit is contained in:
Hanif Dwy Putra S
2022-05-24 06:02:23 +00:00
committed by GitHub
parent fc21150ea5
commit 41dd01d383
4 changed files with 98 additions and 13 deletions

View File

@@ -0,0 +1,40 @@
import {Component, ReactNode} from 'react';
interface Props {
children: ReactNode;
fallback: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
/**
* @class ErrorBoundary
*/
export class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false,
};
/**
* @param {Error} error an error.
* @return {State}
*/
public static getDerivedStateFromError(error: Error): State {
return {hasError: true, error};
}
/**
* Render error.
* @return {JSX.Element}
*/
public render(): JSX.Element {
if (this.state.hasError) {
return this.props.fallback as JSX.Element;
}
return this.props.children as JSX.Element;
}
}

View File

@@ -1,4 +1,6 @@
import React from 'react';
import React, {Suspense} from 'react';
import {ErrorBoundary} from './ErrorBoundary';
import {TikTokVideoComponent} from './Video';
// // ERRORS ///
/**
@@ -13,7 +15,6 @@ class InvalidUrlError extends Error {
this.name = 'INVALID_URL';
}
}
/**
* FormInput Component.
* @return {JSX.Element}
@@ -21,6 +22,7 @@ class InvalidUrlError extends Error {
export const FormInputComponent = (): JSX.Element => {
const [url, setUrl] = React.useState('');
const [error, setError] = React.useState<string | Error>();
const [submitted, setSubmit] = React.useState<boolean>(false);
React.useEffect(() => {
if (
@@ -49,7 +51,10 @@ export const FormInputComponent = (): JSX.Element => {
<form
target="#"
className="flex flex-col md:flex-row"
onSubmit={() => {}}
onSubmit={() => {
!error && setSubmit(true);
return;
}}
>
<div>
<input
@@ -63,13 +68,33 @@ export const FormInputComponent = (): JSX.Element => {
<div>
<button
type="button"
className="p-3 ml-2 bg-sky-400 uppercase text-white"
className="p-3 lg:ml-2 md:mt-2 sm:mt-2 bg-sky-400 uppercase text-white"
disabled={submitted}
>
download
</button>
</div>
</form>
{submitted && (
<ErrorBoundary
fallback={
<h2 className="text-red-500 font-sans font-medium text-base">
Couldn't fetch tiktok's video url
</h2>
}
>
<Suspense
fallback={
<h2 className="font-sans font-medium text-base">
Loading...
</h2>
}
>
<TikTokVideoComponent url={new URL(url)} />
</Suspense>
</ErrorBoundary>
)}
</section>
</React.Fragment>
);

View File

@@ -1,22 +1,42 @@
import React from 'react';
import useSWR, {Fetcher} from 'swr';
import {ExtractedInfo} from 'tiktok-dl-core';
type ExtractedInfoWithProvider = ExtractedInfo & {
export type ExtractedInfoWithProvider = ExtractedInfo & {
provider: string;
};
// fetcher
const fetcher: Fetcher<ExtractedInfoWithProvider, string> = (...args) =>
fetch(...args).then((res) => res.json());
/**
* Render tiktok video component.
* @param {ExtractedInfoWithProvider} data tiktok's api result.
* @param {{ url: URL; }} param0 TikTokVideoComponent props.
* @return {JSX.Element}
*/
export const TikTokVideoComponent = (
data: ExtractedInfoWithProvider,
): JSX.Element => {
export const TikTokVideoComponent = ({url}: {url: URL}): JSX.Element => {
url.search = ''; // clean params.
const {data} = useSWR(
[
'/api/download',
{
method: 'POST',
body: JSON.stringify({url: url.href}),
},
],
fetcher,
{
suspense: true,
},
);
console.log(data);
return (
<React.Fragment>
<section className="mt-5">
{data.error ? (
{data && !data.error ? (
<>
<h1 className="text-base">Here is your video:</h1>
<ul className="flex flex-col md:flex-row flex-grow-0">
@@ -29,7 +49,7 @@ export const TikTokVideoComponent = (
) : (
<>
<h1 className="text-base text-red-500 font-medium">
Error: {data.error}
Error: {data && data.error ? data.error : 'wait'}
</h1>
</>
)}

View File

@@ -9,7 +9,7 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
await ratelimitMiddleware(req, res);
const providersType = Providers.map((p) => p.resourceName());
ow(
req.body || req.query,
req.method === 'POST' ? JSON.parse(req.body) : req.query,
ow.object.partialShape({
url: ow.string.url.validate((v) => ({
validator: