javascript - 编辑后,只有一个字段被编辑,另一个字段出现意外行为(React hooks)

标签 javascript reactjs react-hooks

我有一个非常简单的可编辑书单。但是当我按下“编辑”并只编辑两个字段中的一个时,另一个字段的行为出乎意料(它甚至清除了一个值,或者从上帝那里获取了意想不到的值)。仅当我同时编辑这两个字段时它才能正常工作。

这是我的代码:

import './App.css';
import React, { useState, useEffect } from 'react';


function App() {
const [books, setBooks] = useState([]);
const [book, setBook] = useState({
id: '',
title: '',
author: ''
});

const [alertMessage, setAlertMessage] = useState(false);
const [successMessage, setSuccessMessage] = useState(false);
const [editMode, setEditMode] = useState(null);
const [titleValue, setTitleValue] = useState('');
const [authorValue, setAuthorValue] = useState('');

useEffect(()=> {
const data = localStorage.getItem('books');
if(data) {
  setBooks(JSON.parse(data))
}
}, [])


useEffect(()=> {
localStorage.setItem('books', JSON.stringify(books))
},)


function addBook (e) {
e.preventDefault();
if(!book.title && !book.author){
  setAlertMessage(true)
  setTimeout(()=>setAlertMessage(false), 3000)
} else {
  let newBook = {
    ...book,
    id: Math.floor(Math.random() * 100000000),
  };
  setBooks([newBook, ...books]);
  setBook({
    title: '',
    author: ''
  });
  setSuccessMessage(true)
  setTimeout(()=>setSuccessMessage(false), 1000);
}

}

function deleteBook(id){
setBooks(books.filter(book => book.id !== id))
}

function editBook(id) {
setEditMode(id);
}

function onChange(e) {
setBook({
  ...book,
  [e.target.name]: e.target.value
})

}

function saveChanges (id) {
let newBook = [...books].map(book => {
 if(book.id === id) {
   book.title = titleValue;
   book.author = authorValue
 }
 return book
});
setBook(newBook);
setEditMode(null)
}


return (
<div className='container'>
 
 {alertMessage && <div className='alertMeaage'>Please, enter book author or its title</div>}
 {successMessage && <div className='successMessage'>Book is successfully added!</div>}

 <div className='BookForm'>
   <h3>Add book</h3>
    <input name='title' type='text' placeholder='Enter book title' value={book.title}  onChange={onChange}/>
    <input name='author' type='text' placeholder='Enter book author' value={book.author} onChange={onChange}/>
    <button className='submitBtn' onClick={addBook}>Send</button>
 </div>

 <div>
   <h4>Recently added books:</h4>
  <div key={book.id}>{books.map(book => (
    <div className='bookItem'>
      {editMode !== book.id ? <><span className='titleAuthor'>Title: </span><i>«{book.title}» </i> 
        <span className='titleAuthor'>Author: </span> <i>{book.author}</i>
        <button onClick={()=>deleteBook(book.id)} className='deleteBtn'>X</button>
        <button onClick={()=>editBook(book.id)} className='editBtn'>Edit</button></> 
        : 
    <form className='form'>
      <input name='title' type='text' defaultValue={book.title} onChange={(e)=> setTitleValue(e.target.value)}/>
      <input name='author' type='text' defaultValue={book.author} onChange={(e)=> setAuthorValue(e.target.value)}/>
      <button className='saveBtn' onClick={()=>saveChanges(book.id)}>Save</button>
    </form>
        }
        
    </div>
   ))}
   </div> 
 </div>
</div>
);
 
}

export default App;

提前致谢!

最佳答案

当你编辑新书时,authorValuetitleValue 仍然有以前的值,所以你必须 setAuthorValuesetTitleValue 在 editBook 函数中。见下文:

  function editBook(book) {
    setEditMode(book.id);
    setTitleValue(book.title);
    setAuthorValue(book.author);
  }

并处理事件:

 <button onClick={() => editBook(book)} className="editBtn">
                    Edit
                  </button>

所有代码:

// import './App.css';
import React, { useState, useEffect } from "react";

function App() {
  const [books, setBooks] = useState([]);
  const [book, setBook] = useState({
    id: "",
    title: "",
    author: ""
  });

  const [alertMessage, setAlertMessage] = useState(false);
  const [successMessage, setSuccessMessage] = useState(false);
  const [editMode, setEditMode] = useState(null);
  const [titleValue, setTitleValue] = useState("");
  const [authorValue, setAuthorValue] = useState("");

  useEffect(() => {
    const data = localStorage.getItem("books");
    if (data) {
      setBooks(JSON.parse(data));
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("books", JSON.stringify(books));
  });

  function addBook(e) {
    e.preventDefault();
    if (!book.title && !book.author) {
      setAlertMessage(true);
      setTimeout(() => setAlertMessage(false), 3000);
    } else {
      let newBook = {
        ...book,
        id: Math.floor(Math.random() * 100000000)
      };
      setBooks([newBook, ...books]);
      setBook({
        title: "",
        author: ""
      });
      setSuccessMessage(true);
      setTimeout(() => setSuccessMessage(false), 1000);
    }
  }

  function deleteBook(id) {
    setBooks(books.filter((book) => book.id !== id));
  }

  function editBook(book) {
    setEditMode(book.id);
    setTitleValue(book.title);
    setAuthorValue(book.author);
  }

  function onChange(e) {
    console.log(e.target.name, e.target.value);
    setBook({
      ...book,
      [e.target.name]: e.target.value
    });
  }

  function saveChanges(id) {
    let newBook = [...books].map((book) => {
      if (book.id === id) {
        book.title = titleValue;
        book.author = authorValue;
      }
      return book;
    });
    setBook(newBook);
    setEditMode(null);
  }

  return (
    <div className="container">
      {alertMessage && (
        <div className="alertMeaage">
          Please, enter book author or its title
        </div>
      )}
      {successMessage && (
        <div className="successMessage">Book is successfully added!</div>
      )}

      <div className="BookForm">
        <h3>Add book</h3>
        <input
          name="title"
          type="text"
          placeholder="Enter book title"
          value={book.title}
          onChange={onChange}
        />
        <input
          name="author"
          type="text"
          placeholder="Enter book author"
          value={book.author}
          onChange={onChange}
        />
        <button className="submitBtn" onClick={addBook}>
          Send
        </button>
      </div>

      <div>
        <h4>Recently added books:</h4>
        <div key={book.id}>
          {books.map((book) => (
            <div className="bookItem">
              {editMode !== book.id ? (
                <>
                  <span className="titleAuthor">Title: </span>
                  <i>«{book.title}» </i>
                  <span className="titleAuthor">Author: </span>{" "}
                  <i>{book.author}</i>
                  <button
                    onClick={() => deleteBook(book.id)}
                    className="deleteBtn"
                  >
                    X
                  </button>
                  <button onClick={() => editBook(book)} className="editBtn">
                    Edit
                  </button>
                </>
              ) : (
                <form className="form">
                  <input
                    name="title"
                    type="text"
                    defaultValue={book.title}
                    onChange={(e) => setTitleValue(e.target.value)}
                  />
                  <input
                    name="author"
                    type="text"
                    defaultValue={book.author}
                    onChange={(e) => setAuthorValue(e.target.value)}
                  />
                  <button
                    className="saveBtn"
                    onClick={() => saveChanges(book.id)}
                  >
                    Save
                  </button>
                </form>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

export default App;

关于javascript - 编辑后,只有一个字段被编辑,另一个字段出现意外行为(React hooks),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68441508/

相关文章:

javascript - 静态方法在 ES6 类中未定义,在 reactjs 中带有装饰器

reactjs - 在 useState Hook 中对状态使用类引用

reactjs - TypeError - undefined 不是一个对象(评估 'c.currentObservable.query.refetch' )。在 native react 中

javascript - Reactjs : import and load external js library minified files put inside src

javascript - 设置 "selected"动态改变 html select 的值

javascript - 为什么我的复选框样式不起作用?

javascript - 正确 react 路由器侧边栏路由,但不显示顶部菜单下的组件

reactjs - 从路径显示 Markdown 文件与 typescript react

javascript - 有没有一种通用的方法可以像css的@import一样导入javascript文件?

javascript - Backbone 路线没有哈希就无法工作