【问题标题】:Why is the onClick event triggering twice even though there's e.preventDefault using hooks in React?为什么即使在 React 中有 e.preventDefault 使用钩子,onClick 事件也会触发两次?
【发布时间】:2020-09-06 22:10:16
【问题描述】:

更新:问题直接出在reducer上,与onClick函数和deleteLastItem函数无关。我用 console.logs 对此进行了测试,显然唯一重复两次的是直接在 reducer 中的那个。

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

这是存储上下文和 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;

【问题讨论】:

  • 尝试使用 stopPropagation:stackoverflow.com/questions/36316846/…
  • 这也不是@gtamborero
  • 不确定您是否在此按钮周围有一个表单,也许只需将type="button" 添加到该按钮以查看它是否没有在某处提交表单?
  • 我没有,那也不起作用:( @Dominik
  • 当你将 console.log 添加到你的函数 deleteBook 时,控制台也会记录两次吗?

标签: javascript reactjs react-hooks use-context use-reducer


【解决方案1】:

解决方案如下,我使用过滤器方法更改了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}
  }
}

【讨论】:

    猜你喜欢
    • 2014-10-05
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    相关资源
    最近更新 更多