我正在使用Next.JS
、Prisma
、Typescript
和PostgreSQL
创建一个Todo-App,所有数据都是使用API文件夹获取的,该文件夹使用Prisma
与数据库进行交互,对于Task表的CRUD操作,我只调用端点http:3000/api/tasks
。任务由一个名为To-dos的组件渲染,该组件使用useEffect
获取任务。
一切看起来都很好,但是当任何CRUD操作发生时,客户端中显示的数据不会更新,我需要重新加载页面,强制重新呈现组件以显示新数据。
如何解决此问题?
Todos.tsx:
export default function Todos({ attribute, value, title, limit, addBtn }: arguments) {
const [data, setData] = useState<Item[]>([]);
//fetching data
useEffect(() => {
const fetchData = async () => {
const response: any = await obtenerTasks({ attribute, value, limit });
setData(response.response);
};
fetchData();
}, []);
return (
<div>
<div>
<h1>{title}</h1>
<div className='todos_container'>
{
data.map((item) => (
<Task
key={item.id}
id={item.id}
title={item.title}
description={item.description}
createdAt={item.createdAt}
category={item.category}
completed={item.completed}
priority={item.priority}
dueDate={item.dueDate}
/>
))
}
</div>
</div>
{addBtn && (
<div className='todo_showMore'>
<Link href={`/task/${attribute}?value=${value}`}>
<p>ver mas</p>
</Link>
</div>
)}
</div>
);
}
字符串
lib/task/API_task.ts:
//get tasks
const obtenerTasks = async ({ attribute, value, limit }: TaskProps): Promise<any> => {
try {
let url: string = `http://localhost:3000/api/tasks?attribute=${attribute}&value=${value}`;
if (limit) url += `&limit=${limit}`;
const response = await axios.get(url);
return { response: response.data, status: response.status }
} catch (error) {
throw new Error(String(error));
}
};
//create task
const crearTask = async (task: Task): Promise<any> => {
try {
const url: string = "http://localhost:3000/api/tasks";
const response = await axios.post(url, task);
return { response: response.data, status: response.status }
} catch (error) {
throw new Error(String(error));
}
};
//update task
const actualizarTask = async (task: Task): Promise<any> => {
try {
const url: string = `http://localhost:3000/api/tasks?id=${task.id}`;
const response = await axios.put(url, task);
return { response: response.data, status: response.status }
} catch (error) {
throw new Error(String(error));
}
};
//delete taks
const eliminarTask = async (id: number): Promise<any> => {
try {
const url: string = `http://localhost:3000/api/tasks?id=${id}`;
const response = await axios.delete(url);
return { response: response.data, status: response.status }
} catch (error) {
throw new Error(String(error));
}
};
型
首页.tsx:
<div className="container_todos">
<Todos attribute={"completed"} value={"false"} title={"Pendiente"} limit={3} addBtn={true} />
<Todos attribute={"completed"} value={"true"} title={"Completado"} limit={3} addBtn={true} />
<Todos attribute={"priority"} value={"true"} title={"Prioridad"} limit={3} addBtn={true} />
</div>
型
/API/task/route.tsPrisma与DB的交互
import prisma from '../../../../prisma/client/index';
import { NextResponse } from 'next/server';
//objeto todo con todos sus atributos
type Todo = {
title: string,
description?: string,
category?: string,
createdAt?: string,
dueDate?: string,
priority?: boolean,
completed?: boolean,
}
//metodo GET que obtiene los Task que se filtran en base a sus atributos
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url); //obtener parametros url
const attribute = searchParams.get('attribute'); //obtener el atributo de la URL a buscar
const value = searchParams.get('value'); //obtener el valor del atributo
const limit = searchParams.get('limit'); //obtener el valor del atributo
let isTrue = (value == "true") ? true : false; //variable auxiliar para consultar clausula
let whereClause; //inicializacion de clausula
let todos;
//clausula de consulta a la base de datos
if(attribute && value) {
whereClause = { [attribute as string]: value };
}
//obtener los Task completados o marcados como prioridad
if(attribute == "completed" || attribute == "priority") {
whereClause = { [attribute as string]: isTrue };
}
//query de consulta a la base de datos
if (limit) {
const parsedLimit = parseInt(limit, 10);
if (!isNaN(parsedLimit)) {
todos = await prisma.todo.findMany({
where: whereClause,
take: parsedLimit
});
} else {
todos = await prisma.todo.findMany({
where: whereClause
});
}
} else {
todos = await prisma.todo.findMany({
where: whereClause
});
}
return NextResponse.json(todos);
} catch (error) {
console.log(error);
return NextResponse.json({ error: 'Internal server error' });
}
}
//metodo POST que crea un nuevo task
export async function POST(request: Request) {
try {
const data:Todo = await request.json();
const {title, description, category, createdAt, dueDate, priority, completed} = data;
const todo = await prisma.todo.create({
data: {
title,
description,
category,
createdAt,
dueDate,
priority,
completed,
},
});
return NextResponse.json(todo);
} catch (error) {
console.log(error)
}
}
export async function PUT(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
const data: Todo = await request.json();
const { title, description, category, createdAt, dueDate, priority, completed } = data;
try {
if (id) {
const updatedTodo = await prisma.todo.update({
where: { id: parseInt(id) },
data: {
title,
description,
category,
createdAt,
dueDate,
priority,
completed,
},
});
return NextResponse.json(updatedTodo);
} else {
console.log('Param "id" is not present at URL');
}
} catch (error) {
console.log(error);
}
}
export async function DELETE(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
try {
await prisma.todo.delete({
where: {id: parseInt(id as string) }
});
return NextResponse.json({ msg: `Todo ID ${id} deleted successfully` });
} catch (error) {
console.log(error);
}
}
型
我尝试使用轮询间隔获取数据每5秒,但它的方式太expense,我只是希望数据更新没有realoding网页
1条答案
按热度按时间z8dt9xmd1#
如果状态或属性改变,则react组件重新呈现。
如果你使用的是
useEffect
,如果它的一个依赖项改变了,它的效果会重新运行。由于useEffect
依赖数组为空,这意味着它的效果仅在组件首次呈现时运行。为了重新运行useEffect
效果,您需要添加一个可能会更改的依赖项。即应用程序中data
状态值。但是如果你将data
添加到dependency数组中,这将导致无限循环,因为如果data
状态值更改,它将导致重新渲染应用程序,并且由于useEffect
将依赖于data
状态,它的效果将无限地重新运行。下面的设置应该可以工作。字符串