From a712b6c7b7ca99885a108e34108d0b21011ddc73 Mon Sep 17 00:00:00 2001 From: atybdot <180611249+atybdot@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:00:49 +0530 Subject: [PATCH] removed zustand and migrated to react context api --- biome.json | 3 +- package.json | 15 +++--- pnpm-lock.yaml | 25 ---------- src/components/AuthForm.jsx | 19 +++++--- src/components/Comment.jsx | 77 ++++++++++++++++++++----------- src/components/CommentSection.jsx | 31 ++++++++----- src/components/CustomToast.jsx | 1 + src/components/PostComment.jsx | 9 ++-- src/index.js | 2 +- src/store/commentContext.jsx | 13 ++++++ src/store/commentsStore.js | 24 ---------- 11 files changed, 113 insertions(+), 106 deletions(-) create mode 100644 src/store/commentContext.jsx delete mode 100644 src/store/commentsStore.js diff --git a/biome.json b/biome.json index 778d88b..4887cd4 100644 --- a/biome.json +++ b/biome.json @@ -28,7 +28,8 @@ }, "nursery": { "recommended": true, - "useConsistentMemberAccessibility": "off" + "useConsistentMemberAccessibility": "off", + "noUselessEscapeInRegex": "info" }, "correctness": { "recommended": true, diff --git a/package.json b/package.json index d573100..78785ad 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "description": "seamlessly integrate a comment section into your React or Astro project", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", - "files": ["dist"], + "files": [ + "dist" + ], "scripts": { "build": "rollup -c --bundleConfigAsCjs", "dev": "", @@ -24,16 +26,16 @@ "homepage": "https://github.com/atybdot/app-comment-react", "dependencies": { "appwrite": "^16.0.2", - "react": "^18.3.1", - "react-dom": "^18.3.1", "javascript-time-ago": "^2.5.11", "lucide-react": "^0.453.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-hook-form": "^7.53.1", "react-hot-toast": "^2.4.1", - "react-time-ago": "^7.3.3", - "zustand": "^5.0.0" + "react-time-ago": "^7.3.3" }, "devDependencies": { + "@babel/preset-react": "^7.25.9", "@biomejs/biome": "1.9.4", "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^28.0.1", @@ -49,8 +51,7 @@ "rollup-plugin-dts": "^6.1.1", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", - "tailwindcss": "^3.4.14", - "@babel/preset-react": "^7.25.9" + "tailwindcss": "^3.4.14" }, "publishConfig": { "access": "public" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 02d89e4..675190e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,9 +32,6 @@ importers: react-time-ago: specifier: ^7.3.3 version: 7.3.3(javascript-time-ago@2.5.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - zustand: - specifier: ^5.0.0 - version: 5.0.0(react@18.3.1) devDependencies: '@babel/preset-react': specifier: ^7.25.9 @@ -1474,24 +1471,6 @@ packages: engines: {node: '>= 14'} hasBin: true - zustand@5.0.0: - resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=18.0.0' - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - use-sync-external-store: - optional: true - snapshots: '@alloc/quick-lru@5.2.0': {} @@ -2843,7 +2822,3 @@ snapshots: yaml@1.10.2: {} yaml@2.6.0: {} - - zustand@5.0.0(react@18.3.1): - optionalDependencies: - react: 18.3.1 diff --git a/src/components/AuthForm.jsx b/src/components/AuthForm.jsx index 22b209d..97f3779 100644 --- a/src/components/AuthForm.jsx +++ b/src/components/AuthForm.jsx @@ -1,15 +1,16 @@ import { Eye, EyeOff, X } from "lucide-react" -import { forwardRef, useEffect, useRef, useState } from "react" +import { forwardRef, useEffect, useState } from "react" import { useForm } from "react-hook-form" +import { Loading, onInvalid, onSucess } from "../utils/utils" + import toast from "react-hot-toast" import { emailLogin, emailSignup, getUser } from "../lib/appwrite" -import useCommentStore from "../store/commentsStore" -import { Loading, onInvalid, onSucess } from "../utils/utils" +import useComment from "../store/commentContext" import CustomToast from "./CustomToast" const SignupForm = () => { const [showPassword, setShowPassword] = useState(false) - const { updateUser, updateLoginState } = useCommentStore() + const { updateUser, updateLoginState } = useComment() const { register, handleSubmit, @@ -59,7 +60,9 @@ const SignupForm = () => { { } const LoginForm = () => { - const { updateUser, user, updateLoginState } = useCommentStore() + const { updateLoginState, updateUser } = useComment() const [showPassword, setShowPassword] = useState(false) const { register, @@ -271,6 +274,7 @@ const AuthForm = forwardRef((props, ref) => { ref={ref} > ref.current.close()} className="text-sm absolute top-0 right-0 m-4 dark:text-zinc-100 text-zinc-900 hover:text-blue-500" > @@ -303,6 +307,7 @@ const AuthForm = forwardRef((props, ref) => { > Sign in with Google @@ -316,6 +321,7 @@ const AuthForm = forwardRef((props, ref) => { Sign in with GitHub @@ -325,6 +331,7 @@ const AuthForm = forwardRef((props, ref) => { setIsLogin(!isLogin)} className="font-medium hover:text-blue-600" > diff --git a/src/components/Comment.jsx b/src/components/Comment.jsx index f2c30ad..0d54855 100644 --- a/src/components/Comment.jsx +++ b/src/components/Comment.jsx @@ -4,13 +4,14 @@ import { useForm } from "react-hook-form" import { deleteComment, updateComment } from "../lib/appwrite" import { CreationDate, Loading, onInvalid, onSucess } from "../utils/utils" -import useCommentStore from "../store/commentsStore" +import useComment from "../store/commentContext" export default function Comment({ content: initialContent, username, timestamp, commentId, + permissions = [], }) { const { register, @@ -22,7 +23,10 @@ export default function Comment({ }, }) - const { removeComment, addAComment } = useCommentStore() + const { setComments, user } = useComment() + + const showEdit = permissions.includes(`update("user:${user.id}")`) + const showDel = permissions.includes(`delete("user:${user.id}")`) const [isEditing, setIsEditing] = useState(false) const [editedContent, setEditedContent] = useState(initialContent) @@ -38,24 +42,32 @@ export default function Comment({ } const updateCommentContent = async (data) => { - const res = await updateComment(data.updateCommentContent, commentId) - removeComment(res.$id) - addAComment(res) - isSubmitSuccessful && onSucess("comment updated") - setIsEditing(false) - setEditedContent(data?.updateCommentContent) + try { + const res = await updateComment(data.updateCommentContent, commentId) + setComments((prev) => prev.filter((item) => item.$id !== commentId)) + setComments((prev) => [res, ...prev]) + isSubmitSuccessful && onSucess("comment updated") + setIsEditing(false) + setEditedContent(data?.updateCommentContent) + } catch (error) { + setIsEditing(false) + onInvalid(error.message) + setEditedContent(initialContent) + } } const handleDelete = async () => { setIsDeleting(true) deleteComment(commentId) .then(() => { - removeComment(commentId) + // removeComment(commentId); + setComments((prev) => prev.filter((item) => item.$id !== commentId)) setIsDeleting(false) onSucess("comment deleted") }) .catch((err) => { - onInvalid("unable to delete this comment") + onInvalid(err.message) + setIsDeleting(false) console.error(err) }) } @@ -91,6 +103,7 @@ export default function Comment({ /> @@ -99,6 +112,7 @@ export default function Comment({ @@ -119,22 +133,33 @@ export default function Comment({ )} - - - - - {isDeleting ? : } - {isDeleting ? "deleting..." : ""} - + {showEdit ? ( + + + + ) : null} + + {showDel ? ( + + {isDeleting ? ( + + ) : ( + + )} + {isDeleting ? "deleting..." : ""} + + ) : null} diff --git a/src/components/CommentSection.jsx b/src/components/CommentSection.jsx index 08d09c9..b85d2ad 100644 --- a/src/components/CommentSection.jsx +++ b/src/components/CommentSection.jsx @@ -1,20 +1,17 @@ import { useEffect } from "react" import { Suspense } from "react" +import { useState } from "react" import { commentDB, getUser, logoutUser } from "../lib/appwrite" -import useCommentStore from "../store/commentsStore" +import { CommentProvider } from "../store/commentContext" import { onInvalid, onSucess } from "../utils/utils" import Comment from "./Comment" +import CustomToast from "./CustomToast" import PostComment from "./PostComment" export default function CommentSection({ postId }) { - const { - loginState, - updateUser, - updateLoginState, - user, - comments, - setComments, - } = useCommentStore() + const [loginState, updateLoginState] = useState(false) + const [user, updateUser] = useState({ id: "", name: "" }) + const [comments, setComments] = useState([]) const handleLogout = async () => { try { @@ -50,9 +47,18 @@ export default function CommentSection({ postId }) { }, []) return ( - <> - + + Comments @@ -77,11 +83,12 @@ export default function CommentSection({ postId }) { timestamp={comment.$updatedAt} username={comment.username} commentId={comment.$id} + permissions={comment.$permissions} /> ))} - > + ) } diff --git a/src/components/CustomToast.jsx b/src/components/CustomToast.jsx index fef4833..08aea11 100644 --- a/src/components/CustomToast.jsx +++ b/src/components/CustomToast.jsx @@ -15,6 +15,7 @@ function CustomToast() { {message} {t.type !== "loading" && ( toast.dismiss(t.id)} > diff --git a/src/components/PostComment.jsx b/src/components/PostComment.jsx index 6a13c6d..3232758 100644 --- a/src/components/PostComment.jsx +++ b/src/components/PostComment.jsx @@ -4,10 +4,10 @@ import React from "react" import { Loading, onInvalid, onSucess } from "../utils/utils" import { useForm } from "react-hook-form" -import { addComment, updateComment } from "../lib/appwrite" +import { addComment } from "../lib/appwrite" import AuthForm from "./AuthForm" -import useCommentStore from "../store/commentsStore" +import useComment from "../store/commentContext" export function AddComment({ postId }) { const { @@ -17,7 +17,7 @@ export function AddComment({ postId }) { reset, } = useForm() - const { user, addAComment, comments } = useCommentStore() + const { user, setComments } = useComment() const createComment = async (data) => { const commentData = { @@ -28,7 +28,7 @@ export function AddComment({ postId }) { try { isValid && (await addComment(commentData, user.id).then((data) => { - addAComment(data) + setComments((prev) => [data, ...prev]) })) onSucess("comment added") @@ -86,6 +86,7 @@ function Skeleton() { dialogeRef.current.showModal()} className="text-blue-500" > diff --git a/src/index.js b/src/index.js index 4abb4fe..06987d2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,2 +1,2 @@ import CommentSection from "./components" -export { CommentSection } +export default CommentSection diff --git a/src/store/commentContext.jsx b/src/store/commentContext.jsx new file mode 100644 index 0000000..85ee71e --- /dev/null +++ b/src/store/commentContext.jsx @@ -0,0 +1,13 @@ +import { createContext, useContext } from "react" + +export const CommentContext = createContext({ + loginState: false, + user: { name: "", id: "" }, + comments: [], +}) + +export const CommentProvider = CommentContext.Provider + +export default function useComment() { + return useContext(CommentContext) +} diff --git a/src/store/commentsStore.js b/src/store/commentsStore.js deleted file mode 100644 index 34ee9e2..0000000 --- a/src/store/commentsStore.js +++ /dev/null @@ -1,24 +0,0 @@ -import { create } from "zustand" - -const useCommentStore = create((set) => ({ - loginState: false, - user: { name: "", id: "" }, - comments: ["noice"], - updateLoginState: (newStatus) => { - set(() => ({ loginState: newStatus })) - }, - updateUser: (newUser) => set(() => ({ user: newUser })), - setComments: (newComments) => { - set(() => ({ comments: newComments })) - }, - addAComment: (newCom) => { - set((old) => ({ commnets: old.comments.unshift(newCom) })) - }, - - removeComment: (commentId) => { - set((old) => ({ - comments: old.comments.filter((item) => item?.$id !== commentId), - })) - }, -})) -export default useCommentStore