首页 > 解决方案 > 无效的钩子调用错误 react-redux 钩子

问题描述

我是 react-redux 的新手,我有一个问题。我看了很多网站,但我无法解决这个错误。

错误文本在这里:

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能由于以下原因之一而发生:

  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(这个文件是我使用钩子的地方):

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 />

可能有成千上万的错误,我正在努力应对 react 和 redux ......

问题是什么?你能帮我吗?感谢您的关注。

标签: javascriptreactjsreduxreact-reduxreact-hooks

解决方案


看了你的代码后,我看到了这个。

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

问题在于:

onClick={(inputText = "")}

只有通过创建状态时提供的函数才能更改组件的状态。在您的情况下,该函数被调用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


推荐阅读