Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 上下文Api状态未更改_Javascript_Arrays_Reactjs_Frontend_Context Api - Fatal编程技术网

Javascript 上下文Api状态未更改

Javascript 上下文Api状态未更改,javascript,arrays,reactjs,frontend,context-api,Javascript,Arrays,Reactjs,Frontend,Context Api,我试图在上下文提供程序内调用一个名为deleteTask的函数,该函数使用useContext钩子从使用上下文的组件中调用,该钩子在上下文提供程序的状态下从数组中删除某个项,但是当我这样做时,提供程序的状态根本没有改变,我试图跟踪问题,函数异常,但它似乎是在复制提供程序的范围内执行的?还尝试了一个功能来添加一个任务和im有相同的问题。我还添加了一个函数来设置活动任务,我不知道为什么这个函数可以工作,而其他函数不能。我真的不知道发生了什么,这是代码,请帮助我: tasks-context.jsx

我试图在上下文提供程序内调用一个名为deleteTask的函数,该函数使用useContext钩子从使用上下文的组件中调用,该钩子在上下文提供程序的状态下从数组中删除某个项,但是当我这样做时,提供程序的状态根本没有改变,我试图跟踪问题,函数异常,但它似乎是在复制提供程序的范围内执行的?还尝试了一个功能来添加一个任务和im有相同的问题。我还添加了一个函数来设置活动任务,我不知道为什么这个函数可以工作,而其他函数不能。我真的不知道发生了什么,这是代码,请帮助我:

tasks-context.jsx

import React,{useState}来自“React”;
从“react”导入{useffect};
常数dummyTasks=[{
任务:{
文字:“你好”,
},
关键字:0,
isActive:错误
},
{
任务:{
文本:“你好2”,
},
重点:1,,
isActive:错误
}];
export const TasksContext=React.createContext({});
导出常量任务Provider=(道具)=>{
const[tasks,setTasks]=useState(dummyTasks);
const[activeTask,setActiveTask]=useState();
//不起作用
常量deleteTask=(taskToDeleteKey)=>{
setActiveTask(空);
setTasks(tasks.filter(task=>task.key!==taskToDeleteKey));
};
//这个有效(??)
const handleSelectTask=(taskToSelect,key)=>{
setActiveTask(taskToSelect);
const newTaskArray=tasks.map(task=>{
如果(task.key==key){
task.isActive=true;
}否则{
ficha.isActive=false;
}
返回任务;
});
setTask(newTaskArray);
};
报税表(
{props.children}
);
};
“主要”

Main.jsx

从“React”导入React;
导入“./assets/styles/gestion style.css”;
导入“./assets/styles/icons.css”;
从“../../Context/tasks Context”导入{TasksProvider};
从“./components/TaskContainer.jsx”导入TaskContainer;
主功能(道具){
返回(
);
}
任务容器映射任务数组:

TaskContainer.jsx

import React,{useContext,useffect}来自“React”;
从“/TaskTab”导入TaskTab;
从“../../Context/tasks Context”导入{TasksContext};
功能TaskContainer(道具){
const{tasks}=useContext(TasksContext);
返回(
{tasks?tasks.map(taskTab=>
(  ))
:
无效的
}
);
}
导出默认任务容器;
以及调用上下文函数以删除的任务组件:

TaskTab.jsx

import React,{useContext}来自“React”;
从“../../Context/tasks Context”导入{TasksContext};
功能任务选项卡(道具){
让{task,isActive,taskTabKey}=props;
const{handleSelectTask,deleteTask}=useContext(TasksContext);
const selectTask=()=>{
handleSelectTask(task,taskTabKey);
};
常量handleDelete=()=>{
deleteTask(taskTabKey);
};
返回(

{task.text}

); } 导出默认任务选项卡;
Lucas,这不是上下文或提供者的问题

您面临的问题实际上是一种称为事件冒泡的机制,其中当前处理程序执行,然后是父处理程序

有关事件冒泡的更多信息,请参见此处

在本例中,首先调用handleelete函数,然后调用handleSelect函数

解决方案:事件。停止播放()

将handleDelete和handleSelect函数更改为

  const selectTask = () => {
    console.log("handle select called");
    handleSelectTask(task, taskTabKey);
  };

  const handleDelete = event => {
    console.log("handle delete called");
    event.stopPropagation();
    deleteTask(taskTabKey);
  };
现在检查您的控制台,您将发现只有名为delete的句柄将被打印,这将有望解决您的问题

如果它仍然不起作用,那么一定要让我知道。我将为您创建一个codesandbox版本


祝您编码愉快。

谢谢您提出的好问题

这里发生的事情令人困惑是可以理解的,我花了一段时间才意识到这一点

TL;DR:
handleSelectTask
由于事件传播,每次单击
deleteTask
的按钮时,都会调用提供程序中的
handleSelectTask
handleSelectTask
未使用由
deleteTask
修改的状态,即使它在后面运行,因为它已关闭到初始
tasks
数组


快速解决方案1 停止事件从“删除”按钮单击传播到TaskTab div单击,这可能是所需的行为

// in TaskTab.jsx
const handleDelete = (event) => {
  event.stopPropagation(); // stops event from "bubbling" up the tree
  deleteTask(taskTabKey);
}
在DOM中(也由React模拟),事件在树上“冒泡”,以便父节点可以处理来自其子节点的事件。在本例中,
的子项,这意味着当从按钮触发click事件时,它将首先调用我们想要的
handleDelete
函数,但之后它也将从父div调用
selectTask
函数,这可能是意外的。您可以在上阅读有关事件传播的更多信息


快速解决方案2 写入状态更新以在调用它们时使用中间状态值

// in tasks-context.jsx
const deleteTask = ( taskToDeleteKey ) => {
  setActiveTask(null);
  // use the function version of setting state to read the current value whenever it is run
  setTasks((stateTasks) => stateTasks.filter(task => task.key !== taskToDeleteKey));
}

const handleSelectTask = ( taskToSelect, key ) =>{
  setActiveTask( taskToSelect );
  // updated to use the callback version of the state update
  setTasks((stateTasks) => stateTasks.map( task => {
    // set the correct one to active
  }));
};

使用<代码>的回调版本StasgEngs//Cuff>状态更新,它实际上会在更新应用程序时(包括,尤其是在更新的中间)读取值,这是因为<代码> > HealSeleTeTasks<代码>之后,这意味着它实际看到的数组已被首先运行的

deleteTask
修改!您可以在React文档中阅读有关设置状态的回调变量的更多信息。请注意,此“修复”意味着您的组件仍将调用
handleSelectTask
,即使任务已被删除。这不会有任何不良影响,只是要知道


让我们更详细地了解正在发生的事情:

首先是<
import React, { useContext } from 'react';

import { TasksContext } from '../../Context/tasks-context';

function TaskTab( props ) {
  let { task, isActive, taskTabKey } = props;
  const { handleSelectTask, deleteTask } = useContext( TasksContext );

  const selectTask = ()=>{
    handleSelectTask( task, taskTabKey );
  };

  const handleDelete = () =>{
    deleteTask( taskTabKey );
  };

  return (
    <div onClick={ selectTask }>
      <article className={`${task.type} ${isActive ? 'active' : null}`}>
        <p className="user">{task.text}</p>
        <button onClick={handleDelete}>
          <i className="icon-close"></i>
        </button>
      </article>
    </div>
  );
}

export default TaskTab;
  const selectTask = () => {
    console.log("handle select called");
    handleSelectTask(task, taskTabKey);
  };

  const handleDelete = event => {
    console.log("handle delete called");
    event.stopPropagation();
    deleteTask(taskTabKey);
  };
// in TaskTab.jsx
const handleDelete = (event) => {
  event.stopPropagation(); // stops event from "bubbling" up the tree
  deleteTask(taskTabKey);
}
// in tasks-context.jsx
const deleteTask = ( taskToDeleteKey ) => {
  setActiveTask(null);
  // use the function version of setting state to read the current value whenever it is run
  setTasks((stateTasks) => stateTasks.filter(task => task.key !== taskToDeleteKey));
}

const handleSelectTask = ( taskToSelect, key ) =>{
  setActiveTask( taskToSelect );
  // updated to use the callback version of the state update
  setTasks((stateTasks) => stateTasks.map( task => {
    // set the correct one to active
  }));
};