Projeto para organizar suas metas - Realizei seguindo o evento da RocketSeat do dia 09/09/24 até 15/09/24
Esse o lado do cliente do projeto in.orbit, ele uma aplicao web usando React que consulta dados do Back-End atravs de uma API utilizando o React Query
O projeto foi criado no evento NLW da RocketSeat com nvel intermedirio com tutoria do Diego Fernandes.
Abaixo vou dar destaque a alguns pontos que para mim foram destaque do projeto, ou por ser minha primeira experincia usando ou por ser chave no projeto.
Sendo sincero, nem conhecia essa lib e tambm nunca fui um grande apoiador dessas libs que disponibilizam uma UI pr-pronta.
Isso porque acredito que seja importante conseguir criar do 0 sem ser dependende de uma lib assim, mas achei muito interessante trabalhar com uma lib dessa pela primeira vez, quem sabe um dia me aprofunde.
No caso nos foi disponibilizado uma pasta chamada "ui" com os componentes usando @radix-ui j criados
src/components/ui
npm i @radix ui
src/components/ui/progress-bar.tsx
import * as ProgressPrimitive from '@radix-ui/react-progress'
export function Progress(props: ProgressPrimitive.ProgressProps) {
return (
<ProgressPrimitive.Progress
{...props}
className="bg-zinc-900 rounded-full h-2"
/>
)
}
export function ProgressIndicator(
props: ProgressPrimitive.ProgressIndicatorProps
) {
return (
<ProgressPrimitive.Indicator
{...props}
className="bg-gradient-to-r from-pink-500 to-violet-500 w-1/2 h-2 rounded-full"
/>
)
}
{/* Restante dos imports */}
import { Progress, ProgressIndicator } from './ui/progress-bar'
export default function Summary() {
{/* Restante das operaes */}
return (
{/* Outros componentes acima */}
<Progress value={8} max={15}>
{/* completedPercentage => Varivel nmerica */}
<ProgressIndicator style={{ width: `${completedPercentage}%` }} />
</Progress>
{/* Outros componentes abaixo */}
)
}
Nunca havia usado antes, mas defitivamente mudou minhas perspectiva quanto a requisies http usando React, definitivamente no vou mais usar o bom e velho useEffect para isso...
npm i @tanstack/react-query
Para podermos utilizar o React Query na nossa aplicao precisamos implementar nosso provider no arquivo raiz que engloba os demais, no caso main.tsx
src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './app'
import './index.css'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient()
createRoot(document.getElementById('root')!).render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</StrictMode>
)
O useQuery muito mais eficiente que o mtodo "nativo" por inumeros motivos, mas principalmente pois possivel cancelar requisies, requisitar novamente ou definir um tempo entre a requisio atual ou a prxima com muita facilidade, assim ganhando muito desempenho.
Abaixo deixo um exemplo da realizao de uma requisio http:
src/components/summary.tsx
import { useQuery } from '@tanstack/react-query'
export default function Summary() {
const { data: summary } = useQuery({
queryKey: ['summary'],
queryFn: getSummary,
staleTime: 1000 * 60,
})
if (!summary?.at(0)) {
return null
}
return (
<h1>Todas as tarefas cadastradas: {summary[0].total}</h1>
)
}
Para "cancelar" uma requisio antiga e renova-l muito tranquilo, basta declarar um "useQueryClient" e utilizar o mtodo ".invalidateQueries", deixo abaixo um exemplo de componente que usa o useQuery e o useQueryClient
src/components/pending-goals.tsx
import { Plus } from 'lucide-react'
import { OutlineButton } from './ui/outline-button'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { getPendingGoals } from '../http/get-pending-goals'
import { createGoalCompletion } from '../http/create-goal-completion'
import { deleteGoal } from '../http/delete-goal'
export default function PendingGoals() {
const queryClient = useQueryClient()
const { data: pendingGoals } = useQuery({
queryKey: ['pending-goals'],
queryFn: getPendingGoals,
staleTime: 1000 * 60,
})
if (!pendingGoals) {
return null
}
async function handleCompleteGoal(goalId: string) {
await createGoalCompletion(goalId)
queryClient.invalidateQueries({ queryKey: ['summary'] })
queryClient.invalidateQueries({ queryKey: ['pending-goals'] })
}
async function handleDeleteGoal(goalId: string) {
await deleteGoal(goalId)
queryClient.invalidateQueries({ queryKey: ['summary'] })
queryClient.invalidateQueries({ queryKey: ['pending-goals'] })
}
return (
<div className="flex flex-wrap gap-3">
{pendingGoals.map(goal => {
return (
<OutlineButton
onClick={() => handleCompleteGoal(goal.id)}
onDoubleClick={() => handleDeleteGoal(goal.id)}
key={goal.id}
disabled={goal.completionCount >= goal.desiredWeeklyFrequency}
>
<Plus className="size-4 text-zinc-600" />
{goal.title}
</OutlineButton>
)
})}
</div>
)
}
https://github.com/user-attachments/assets/cb45546f-88de-4c97-a723-a62caa3a5aae