为什么 onClick 事件触发两次,即使 React 中使用钩子有 e.preventDefault?



更新:问题直接出现在reducer中,与onClick函数和deleteLastItem函数无关。我用console.log测试了这一点,显然唯一重复两次的是直接在reducer中的一次

我同时测试了钩子useReducer和useContext,因为我认为它们可以很好地协同工作,但很明显,当我将一个函数设置为onClick函数时,它会被触发两次,而最根本的是它不会被触发,因为我正在从数组中删除最后一个项,所以它会删除两个项,而不是一个。

以下是存储上下文和reducer挂钩的文件:

import React, {createContext, useReducer} from "react";
const initialState = {
books: [
{name: "Book 8", autor: "Author 8", id: 8},
{name: "Book 7", autor: "Author 7", id: 7},
{name: "Book 6", autor: "Author 6", id: 6},
{name: "Book 5", autor: "Author 5", id: 5},
{name: "Book 4", autor: "Author 4", id: 4},
{name: "Book 3", autor: "Author 3", id: 3}
]
}
const reducer = (state, action) => {
switch (action.type) {
case "DELETE":
state.books.pop();
console.log("hey");
return {...state}
default:
return {...state}
}
}
export const BookContext = createContext();
export const BookProvider = props => {
const [state, dispatch] = useReducer(reducer, initialState);
// Actions
const deleteLastBook = () => dispatch({type: "DELETE"});
return (
<BookContext.Provider value={{books: state.books, deleteLastBook}}>
{props.children}
</BookContext.Provider>
)
}

正如你所看到的,console.log("hey")是告诉我它被执行了两次(除了看到屏幕上的项目一次被删除两次(

以下是引入上下文和出现问题的组件:

import React, {useContext} from 'react';
import {BookContext} from "../context/BookContext";
const Books = () => {
const information = useContext(BookContext);
const {books, deleteLastBook} = information;
const deleteBook = e => {
e.preventDefault();
deleteLastBook();
};
return (
<div>
{console.log(books)}
{books.map(book => (<h1 key={book.id}>{book.name}</h1>))}
<button onClick={deleteBook}>Delete book</button>
</div>
)
}
export default Books;

最后,这里是app.js,我认为它不会有用,只是以防万一:

import React from 'react';
import './App.css';
import {BookProvider} from "./context/BookContext";
import Books from "./components/Books";
const App = () => {
return (
<BookProvider>
<div className="App">
<Books />
</div>
</BookProvider>
);
}
export default App;

解决方案如下,我使用filter方法更改了reducer返回语句,它成功了:

const reducer = (state, action) => {
switch (action.type) {
case "DELETE":
const lastItem = state.books[state.books.length - 1];
return {
...state,
books: state.books.filter(book => book !== lastItem)
}
default:
return {...state}
}
}

相关内容

最新更新