reactjs - 已解决:为什么 Django 管理员列表没有从前端 React js 表单更新编辑?
问题描述
我正在尝试按照Tania rascia 的示例在 DRF-Reactjs 中制作一个 CRUD 应用程序
我已经成功实现了添加、删除、列表视图。但我正在尝试编辑未在 DRF 后端更新的特定行。但编辑的行显示在前端列表中。为什么它没有在 django 管理列表中更新?
在 DRF 侧 views.py 中:
@api_view(['POST'])
def TodoUpdate(request, pk):
todo = Todo.objects.get(id=pk)
serializer = TodoSerializer(instance=todo, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
我正在使用 cors 标头在前端到后端之间进行接口。这是编辑的前端代码:
应用程序.js:
import React,{Fragment, useState,useEffect} from 'react'
import EditList from './components/EditList';
import axios from 'axios'
export default function App() {
const initialTodoSate = { id: null, title: "", body: "" };
const [todos, setTodos] = useState([]);
const [todoList, setTodolist] = useState(initialTodoSate);
const [editing, setEditing] = useState(false);
useEffect(()=>{
axios.get("http://localhost:8000/api/todo-list",{})
.then(res=>{
setTodos(res.data)
}).catch(err=>{
console.log(err)
})
},[])
const addTodoList = (todo) => {
axios
.post("http://localhost:8000/api/todo-create/",todo)
.then((res) => {
console.log(res.data);
todo.id = todos.length + 1;
setTodos([todo, ...todos]);
})
.catch((err) => {
console.log(err);
});
};
const deleteTodo = (id) => {
setEditing(false);
axios.delete(`http://localhost:8000/api/todo-delete/${id}/`)
.then(res=>{
setTodos(todos.filter((todo) => todo.id !== id));
}).catch(err=>{
console.log(err)
})
};
const updateTodo = ( id,updatedTodo) => {
axios
.post(`http://localhost:8000/api/todo-update/${id}/`, id)
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
setEditing(false);
setTodos(todos.map((todo) => (todo.id === id ? updatedTodo : todo)));
};
const editRow = (todo) => {
setEditing(true);
setTodolist({
id: todo.id,
title: todo.title,
description: todo.description,
});
};
return (
<div className="container">
<h1>Django-based Todo with React Hooks</h1>
{editing ? (
<Fragment>
<h3>Edit Task</h3>
<EditList
editing={editing}
setEditing={setEditing}
todoList={todoList}
updateTodo={updateTodo}
/>
</Fragment>
) : (
<Fragment>
<CreateTodo addTodoList={addTodoList} />
<hr />
</Fragment>
)}
<div className="flex-row">
<div className="flex-large">
<TodoList todos={todos} editRow={editRow} deleteTodo={deleteTodo} />
</div>
</div>
</div>
);
}
和 EditList.js:
import React, { useState,useEffect } from "react";
export default function EditList({ todoList, setEditing, updateTodo }) {
const [todo, setTodo] = useState([todoList]);
useEffect(() => {
setTodo(todoList);
}, [todoList]);
const handleChange = (e) => {
const { name, value } = e.target;
setTodo({ ...todo, [name]: value });
};
return (
<form
onSubmit={(e) => {
e.preventDefault();
updateTodo(todo.id, todo);
}}
>
<label>Title:</label>
<br />
<input
type="text"
name="title"
value={todo.title}
onChange={handleChange}
/>
<br />
<label>Description:</label>
<br />
<input
type="text"
name="body"
value={todo.body}
onChange={handleChange}
/>
<br />
<button>Update Task</button>
<button onClick={() => setEditing(false)} className="button muted-button">
Cancel
</button>
</form>
);
}
当我尝试用标题和正文编辑一行时,它被编辑并在按下更新按钮后,更新的行包含在列表中。但问题是当我查看 django admin 时它还没有更新,当我检查开发工具时,我发现了一个错误:
警告:组件正在更改要控制的非受控输入。这可能是由于值从未定义更改为已定义值引起的,这不应该发生。决定在组件的生命周期内使用受控输入元素还是不受控输入元素。更多信息:https://reactjs.org/link/controlled-components 在 EditList (http://localhost:3000/static/js/main.chunk.js:511:3) 在 App 的 div ( http://localhost:3000/static/js/main.chunk.js:70:83) 控制台。@供应商~main.chunk.js:31671
我哪里错了?
谁能帮帮我?如果您需要任何其他代码或信息,请告诉我。
解决方案
- 尝试更新某些内容应该在 put 请求中完成,而不是在 post 请求中完成。这是一个 REST API 约定,但差异可能会产生一些后果。
- 在这种情况下,您的开发工具中的错误告诉您,您的一个组件具有 onChange/onSubmit 等属性,该属性在一次安装过程中从 null 变为函数。这不是导致您的问题的原因,但我怀疑可以通过在 handleSubmit 函数中声明代码然后将其放入您的 onSubmit 来修复它。
- 我认为实际上导致您的问题的错误是 updatedTodo 没有被发送到后端。发送的只是 id(axios.post 的第二个参数)。所以如果你在执行期间暂停后端,你会看到 request.data = id only,它应该是 TodoSerializer 的可读字段。
PS:
- 您可以添加“调试器”;在 updateToDo 异步请求错误之后的代码中声明以查看错误实际上是什么(阅读更多关于开发工具调试的信息 - 取决于浏览器)。
- 不要滥用片段——在这种情况下,如果您在大多数这些组件中使用 div,它会带来更易于访问的体验。如果将某些内容的标题与内容分组,不是更有意义吗?https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters
推荐阅读
- c# - 使用 Dapper 查询单个项目并转换为模型
- python - 计算序列中的子序列数,其间有最大允许事件
- java - 有没有办法在Java中制作交替的正负数序列?
- windows - 资源取消链接后如何在windows中删除python 3.8共享内存文件
- outlook - Outlook 加载项在 Windows Server 的 2019 桌面客户端中不起作用
- python - 使用 rosbags-libary (PyPI) 创建包含图像和时间戳的 rosbag 文件,而不依赖于 ROS
- python - 在间隙处拆分时间序列数据(pd.Series)的更有效方法?
- android - 我在 react native 中制作了一个按钮来更改应用程序的语言。当我运行应用程序时它工作正常,但它在发布 apk 中不起作用
- react-native - 如何从堆栈导航中删除屏幕 React native
- javascript - 为什么数组读取值不存在?