Skip to content

Commit

Permalink
feat: converted component to hooks API, closes #49
Browse files Browse the repository at this point in the history
  • Loading branch information
matteobruni committed Sep 4, 2023
1 parent 25ad0c5 commit 4a9eaa0
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 200 deletions.
2 changes: 1 addition & 1 deletion components/react/package.dist.json
Expand Up @@ -88,7 +88,7 @@
"unpkg": "particles.min.js",
"jsdelivr": "particles.min.js",
"peerDependencies": {
"react": ">=16"
"react": ">=16.8.0"
},
"dependencies": {
"@tsparticles/engine": "^3.0.0-beta.1"
Expand Down
3 changes: 0 additions & 3 deletions components/react/src/IParticlesProps.ts
Expand Up @@ -3,12 +3,9 @@ import type { CSSProperties } from "react";

export interface IParticlesProps {
id?: string;
width?: string;
height?: string;
options?: ISourceOptions;
url?: string;
style?: CSSProperties;
className?: string;
canvasClassName?: string;
particlesLoaded?: (container?: Container) => Promise<void>;
}
6 changes: 0 additions & 6 deletions components/react/src/IParticlesState.ts

This file was deleted.

138 changes: 16 additions & 122 deletions components/react/src/Particles.tsx
@@ -1,130 +1,24 @@
import React, { Component, ReactNode } from "react";
import { tsParticles } from "@tsparticles/engine";
import React, { useEffect } from "react";
import type { IParticlesProps } from "./IParticlesProps";
import type { IParticlesState } from "./IParticlesState";
import { deepCompare } from "./Utils";
import { tsParticles, type Container } from "@tsparticles/engine";

const defaultId = "tsparticles";
function Particles(props: IParticlesProps): JSX.Element {
const id = props.id ?? "tsparticles";
const [container, setContainer] = React.useState<Container | undefined>(undefined);

/**
* @param {{id?: string,width?: string,height?: string,options?: import("@tsparticles/engine").ISourceOptions,params?: import("@tsparticles/engine").ISourceOptions,style?: import("react").CSSProperties,className?: string,canvasClassName?: string,container?: RefObject<Container>}}
*/
export default class Particles extends Component<IParticlesProps, IParticlesState> {
static defaultProps: IParticlesProps = {
width: "100%",
height: "100%",
options: {},
style: {},
url: undefined,
id: defaultId,
};
useEffect(() => {
tsParticles.load({ id, url: props.url, options: props.options }).then(c => {
setContainer(c);

constructor(props: IParticlesProps) {
super(props);

this.state = {
init: false,
library: undefined,
};
}

destroy(): void {
if (!this.state.library) {
return;
}

this.state.library.destroy();

this.setState({
library: undefined,
props.particlesLoaded?.(c);
});
}

shouldComponentUpdate(nextProps: Readonly<IParticlesProps>): boolean {
const nextOptions = nextProps.options,
currentOptions = this.props.options;

return (
nextProps.url !== this.props.url ||
nextProps.id !== this.props.id ||
nextProps.canvasClassName !== this.props.canvasClassName ||
nextProps.className !== this.props.className ||
nextProps.height !== this.props.height ||
nextProps.width !== this.props.width ||
!deepCompare(nextProps.style, this.props.style) ||
nextProps.particlesLoaded !== this.props.particlesLoaded ||
!deepCompare(nextOptions, currentOptions, key => key.startsWith("_"))
);
}

componentDidUpdate(): void {
this.refresh();
}

forceUpdate(): void {
this.refresh().then(() => {
super.forceUpdate();
});
}

componentDidMount(): void {
(async () => {
this.setState(
{
init: true,
},
async () => {
await this.loadParticles();
},
);
})();
}

componentWillUnmount(): void {
this.destroy();
}

render(): ReactNode {
const { width, height, className, canvasClassName, id } = this.props;

return (
<div className={className} id={id}>
<canvas
className={canvasClassName}
style={{
...this.props.style,
width,
height,
}}
/>
</div>
);
}

private async refresh(): Promise<void> {
this.destroy();

await this.loadParticles();
}

private async loadParticles(): Promise<void> {
if (!this.state.init) {
return;
}

const id = this.props.id ?? Particles.defaultProps.id ?? defaultId,
container = await tsParticles.load({
url: this.props.url,
id,
options: this.props.options,
});

this.setState({
library: container,
});
return () => {
container?.destroy();
};
}, []);

if (this.props.particlesLoaded) {
await this.props.particlesLoaded(container);
}
}
return <div id={id} className={props.className}></div>;
}

export default Particles;
67 changes: 0 additions & 67 deletions components/react/src/Utils.ts

This file was deleted.

1 change: 0 additions & 1 deletion components/react/src/index.ts
Expand Up @@ -3,7 +3,6 @@ import Particles from "./Particles";
import { useEffect, useState } from "react";

export type { IParticlesProps, IParticlesProps as ParticlesProps } from "./IParticlesProps";
export type { IParticlesState, IParticlesState as ParticlesState } from "./IParticlesState";

export function useParticlesPlugins(cb: (engine: Engine) => Promise<void>): { done: boolean; error: boolean } {
const [done, setDone] = useState(false),
Expand Down

0 comments on commit 4a9eaa0

Please sign in to comment.