簡體   English   中英

無效的鈎子調用錯誤 react-redux hooks

[英]Invalid hook call error react-redux hooks

我是 react-redux 的新人,我遇到了問題。 我看了很多網站,但我無法解決這個錯誤。

錯誤文本在這里:

錯誤:無效掛鈎調用。 鈎子只能在 function 組件的內部調用。 這可能由於以下原因之一而發生:

  1. 您可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 你可能違反了 Hooks 規則
  3. 你可能在同一個應用程序中有多個 React 副本

這是我的 index.js 文件:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {Provider} from 'react-redux';
import { createStore } from 'redux'
import all from './reducers/index'

const store = createStore(all)
ReactDOM.render(
  <React.StrictMode>
    <Provider store ={store}>
    <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

這是我的../reducers/index.js 文件:

import {
  combineReducers
} from "redux";
import TodoReducer from "./TodoReducer";
import filterReducer from "./filterReducer";

const all = combineReducers({
  TodoReducer,
  filterReducer,
});

export default all;

filterReducer.js

    import { SHOW_ALL, VISIBILITY_FILTER } from "../actions/actionTypes"; 
    
    const filterReducer = (state = SHOW_ALL, action) => {
      switch (action.type) {
        case "VISIBILITY_FILTER":
          return action.filter;
        default:
          return state;
      }
    };
    
    export default filterReducer;

TodoReducer.js

 import { ADD_TODO, DELETE_TODO, TOGGLE_TODO } from "../actions/actionTypes";
    
    const TodoReducer = (state = [], action) => {
      switch (action.type) {
        case "ADD_TODO":
          return [
            ...state, //todos
            {
              id: action.id,
              text: action.text,
              completed: false,
            },
          ];
    
        case "TOGGLE_TODO":
          return state.map((todo) =>
            todo.id === action.id
              ? {
                  ...todo,
                  completed: !todo.completed,
                }
              : todo
          );
    
        case "DELETE_TODO":
          const numIndex = parseInt(action.id);
          return state.filter((todo) => todo.id !== numIndex);
        default:
          return state;
      }
    };
    
    export default TodoReducer;

actionTypes.js

export const ADD_TODO = 'ADD_TODO'
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const DELETE_TODO = 'DELETE_TODO'
export const SHOW_ALL = 'SHOW_ALL'
export const VISIBILITY_FILTER = 'VISIBILITY_FILTER'

動作.js

import { ADD_TODO, DELETE_TODO, TOGGLE_TODO, VISIBILITY_FILTER } from './actionTypes'

let TodoId = 0

export const addTodo = text => ({
    type: ADD_TODO,
    id: TodoId++,
    text
})

export const deleteTodo = (id) => ({
    type: DELETE_TODO,
    id: id
})

export const toggleTodo = (id) => ({
    type: TOGGLE_TODO,
    id: id
})

export const visibility_filter = filter => ({
  type: VISIBILITY_FILTER,
  filter
})

這是 Todos.js(這個文件是我使用 hook 的地方):

import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addTodo } from "../actions/actions";

const Todos = () => {
  const todos = useSelector((state) => state.todos);

  const dispatch = useDispatch();

  const onAddTodo = () =>
    dispatch(
      addTodo(inputText),
      todos.map((todo) => <div key={todo.id}>{todo.text}</div>)
    );

  const [inputText, setInputText] = useState("");

  const inputTextHandler = (e) => {
    setInputText(e.target.value);
  };

  return (
    <div>
      <div className="form-group row">
        <div className="col-sm-10">
          <input
            onChange={inputTextHandler}
            value={inputText}
            type="text"
            className="form-control"
            id="inputEmail3"
            placeholder="add todo here"
          />
          <button
            type="button"
            onClick={() => setInputText("")}
            style={{ marginTop: "25px", marginRight: "15px" }}
            className="btn btn-danger"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={onAddTodo}
            style={{ marginTop: "25px" }}
            className="btn btn-success"
          >
            Add Todo
          </button>
        </div>
      </div>
    </div>
  );
};

export default Todos;

這是 App.js:

import React from "react";
import Table from './components/Table'; // this file is empty for now
import Todos from './components/Todos'

function App() {
  return (
    <div className="App">
        <div className="container" style={{ marginTop: "80px"}} >
          <div className="row">
            <div className="col-lg-10 offset-lg-2 col-md-10 col-sm-12 col-xs-12">
              <Todos />
            </div>
            <Table />
          </div>
        </div>
      </div>
  );
}

export default App;

這是錯誤代碼:

   8 | import all from './reducers/index'
   9 | 
  10 | const store = createStore(all,)
> 11 | ReactDOM.render(
  12 |   <React.StrictMode>
  13 |     <Provider store ={store}>
  14 |     <App />

可能有成千上萬的錯誤,我正在努力做出反應,redux 太難了......

問題是什么? 你能幫我嗎? 感謝您的關注。

首先,我想建議切換到使用 redux 的掛鈎,因為它們簡化了一切。

您可以從react-redux導入useDispatchuseSelector而不是connect ,並使用它們(鈎子)來訪問和改變您的 redux state。

例如


import { useSelector, useDispatch } from "react-redux"

import { addTodo } from "../actions/actions"

export const Todo = () => {

  //accessing your list of todos
   const todos = useSelector(state => state.todos)
  
  //dispatching an action
  const dispatch = useDispatch()

   const onAddTodo = () => dispatch(addTodo(someData))


   return (
    <div>
      <div className="form-group row">
        <div className="col-sm-10">
          <input
            onChange={inputTextHandler}
            value={inputText}
            type="text"
            className="form-control"
            id="inputEmail3"
            placeholder="add todo here"
          />
          <button
            type="button"
            onClick={() => setinputText("")}
            style={{ marginTop: "25px", marginRight: "15px" }}
            className="btn btn-danger"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={onAddTodo}
            style={{ marginTop: "25px" }}
            className="btn btn-success"
          >
            Add Todo
          </button>
        </div>
      </div>
    </div>
  );
}

一般使用鈎子時,有一點你需要了解,鈎子是在主組件內部聲明的。

您不能在組件的另一個 function 內聲明一個鈎子。

例如

讓我們使用上面的代碼作為示例。 在上面的代碼中,我們定義onAddTodo function,我們過去常常將一個動作分派給我們的 redux state。我們如何做上面的代碼是正確的,但會有一種情況我們可能會出錯,反應當然會拋出這樣的錯誤你目前面對的那個。

下面是使用鈎子的錯誤方法,因為它是在不是主要組件的 function 內部聲明或啟動的。

const onAddTodo = () => {
   //WRONG...
   const dispatch = useDispatch()

   dispatch(addTodo(someData))
}

查看您的代碼后,我看到了這一點。

 <button
            type="button"
            onClick={(inputText = "")}
            style={{ marginTop: "25px", marginRight: "15px" }}
            className="btn btn-danger"
          >

問題在於:

onClick={(inputText = "")}

組件的 state 只能使用創建 state 時提供的 function 進行更改。在您的情況下,function 稱為setInputText

你的按鈕應該是這樣的:

const handleInputReset = () => setInputText('');

<button
                type="button"
                onClick={handleInputReset}
                style={{ marginTop: "25px", marginRight: "15px" }}
                className="btn btn-danger"
              >

參考: https://reactjs.org/docs/hooks-state.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM