0

更新: 問題はレデューサーに直接あり、onClick 関数や deleteLastItem 関数とは関係ありません。これをconsole.logsでテストしましたが、明らかに2回繰り返されるのは、レデューサーに直接あるものだけです。

フック useReducer と useContext を同時にテストしていたのは、それらが非常にうまく連携できると思ったからですが、どうやら、関数を onClick 関数に設定すると、2 回トリガーされます。配列から最後のアイテムを削除しているため、1 つではなく 2 つのアイテムが削除されます。

コンテキストとレデューサー フックが格納されているファイルは次のとおりです。

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"), は、それが 2 回実行されていることを示しています (画面内のアイテムが一度に 2 回消去されていることを除いて)。

コンテキストが取り込まれ、問題が発生するコンポーネントは次のとおりです。

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;
4

1 に答える 1