无效的钩子调用问题。钩子只能在函数组件体内调用

问题描述 投票:0回答:1

我想使用 React 创建待办事项应用程序,我使用 useContext 挂钩,但遇到以下问题

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

  1. 您的 React 和渲染器版本可能不匹配(例如 React DOM)
  2. 你可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本

import { useState } from 'react'
import TodoStore from './Hooks/TodoStore'
import './App.css'
import TodosForm from './Component/TodosForm'
import Tasks from './Component/Tasks'
function App() {
const [todolist,setTodoList]=useState([]);
const fillTodoList=(todo)=>{
  setTodoList([todo,...todolist])
}
  return (
    <TodoStore.Provider value={setTodoList}>
    <TodosForm fillTodoList={fillTodoList} />
    <Tasks alltasks={todolist} setList={setTodoList}/>
    </TodoStore.Provider>
  )
}

export default App

import React from 'react'
import Completed from '../Operations/Completed'
import deleteTask from '../Operations/deleteTask'

function Tasks(props) {
  return (
    <div>
        {
            props.alltasks.map((item)=><div  key={item.id}>
            <span onClick={()=>Completed(item.id,props.alltasks)}>{item.text}</span>
            <button onClick={()=>deleteTask(item.id,props.alltasks)}>X</button>
            </div>)
        }
       
    </div>
  )
}

export default Tasks
import { useContext } from "react"
import TodoStore from "../Hooks/TodoStore"
const deleteTask=(id,alltasks)=>{
const {setList}=useContext(TodoStore);
const result=alltasks.filter((item)=>item.id!=id)
setList([...result])
}
export default deleteTask


javascript reactjs hook
1个回答
0
投票

问题来自于你的

deleteTask
函数:你正在使用一个钩子(
useContext
),但这个函数本身并不是一个钩子。

你必须明白,React 必须为组件的每次渲染渲染精确的相同数量的钩子。所以你不能在嵌套函数中使用钩子(除非它也是一个钩子)

最好的方法

在上下文中使用 reducer,这样您就不必编写多个操作来修改上下文。它是通量模式的基础。它将让你拥有更简洁、更进化的代码。

最快(但有点脏)的方法

您可以将“deleteTask”函数转换为自定义钩子并在任务组件中使用它
import { useContext } from "react"
import TodoStore from "../Hooks/TodoStore"

// Note that hook must always starts with "use"
const useDeleteTask = () => {
    const {setList} = useContext(TodoStore);
    return (id, alltasks) => {
        const result = alltasks.filter((item) => item.id != id)
        setList([...result])
    }
}
export default useDeleteTask

您的任务组件

function Tasks(props) {
    const deleteTask = useDeleteTask()
    return (
        <div>
            {
                props.alltasks.map((item) => <div key={item.id}>
                    <span onClick={()=>Completed(item.id,props.alltasks)}>{item.text}</span>
                    <button onClick={() => deleteTask(item.id,props.alltasks)}>X</button>
                </div>)
            }
        </div>
    )
}

请注意,您不必传递

allTodos
属性,因为它是上下文的一部分,因此您可以使用
useContext
获取它。

希望能解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.