首页 > 解决方案 > 已解决:为什么 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

我哪里错了?

谁能帮帮我?如果您需要任何其他代码或信息,请告诉我。

标签: reactjsdjangodjango-rest-frameworkreact-hooksuse-effect

解决方案


  1. 尝试更新某些内容应该在 put 请求中完成,而不是在 post 请求中完成。这是一个 REST API 约定,但差异可能会产生一些后果。
  2. 在这种情况下,您的开发工具中的错误告诉您,您的一个组件具有 onChange/onSubmit 等属性,该属性在一次安装过程中从 null 变为函数。这不是导致您的问题的原因,但我怀疑可以通过在 handleSubmit 函数中声明代码然后将其放入您的 onSubmit 来修复它。
  3. 我认为实际上导致您的问题的错误是 updatedTodo 没有被发送到后端。发送的只是 id(axios.post 的第二个参数)。所以如果你在执行期间暂停后端,你会看到 request.data = id only,它应该是 TodoSerializer 的可读字段。

PS:

  1. 您可以添加“调试器”;在 updateToDo 异步请求错误之后的代码中声明以查看错误实际上是什么(阅读更多关于开发工具调试的信息 - 取决于浏览器)。
  2. 不要滥用片段——在这种情况下,如果您在大多数这些组件中使用 div,它会带来更易于访问的体验。如果将某些内容的标题与内容分组,不是更有意义吗?https://developers.google.com/web/fundamentals/accessibility/focus/dom-order-matters

推荐阅读