Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.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 如何使用react-useState和useContext模拟消息/事件?_Javascript_Reactjs_Typescript_React Hooks - Fatal编程技术网

Javascript 如何使用react-useState和useContext模拟消息/事件?

Javascript 如何使用react-useState和useContext模拟消息/事件?,javascript,reactjs,typescript,react-hooks,Javascript,Reactjs,Typescript,React Hooks,我正在创建一个带有useState和useContext的react应用程序,用于状态管理。到目前为止,这很有魅力,但现在我遇到了一个需要类似事件的功能: 假设有一个ContentPage,它呈现许多内容片段。用户可以滚动浏览此页面并阅读内容。 还有一个书签页面。单击书签打开ContentPage并滚动到相应的内容 此滚动到内容是一次性操作。理想情况下,我希望在ContentPage中有一个使用ScrollTo(item)事件的事件侦听器。但是react几乎阻止了所有事件的使用。无法在虚拟DOM

我正在创建一个带有useState和useContext的react应用程序,用于状态管理。到目前为止,这很有魅力,但现在我遇到了一个需要类似事件的功能:

假设有一个ContentPage,它呈现许多内容片段。用户可以滚动浏览此页面并阅读内容。
还有一个书签页面。单击书签打开ContentPage并滚动到相应的内容

此滚动到内容是一次性操作。理想情况下,我希望在ContentPage中有一个使用
ScrollTo(item)
事件的事件侦听器。但是react几乎阻止了所有事件的使用。无法在虚拟DOM中捕获DOM事件,并且无法创建自定义合成事件。
此外,命令“openupcontentpiecxyz”可以来自组件树中的许多部分(示例并不完全适合我尝试实现的内容)。一个只会在树上冒泡的事件并不能解决问题

所以我猜反应的方式是用app state来表示这个事件

我有一个变通的解决方案,但它是黑客和有一个问题(这就是为什么我张贴这个问题):

导出接口消息队列{
信息:号码[],
推送:(num:number)=>void,
pop:()=>编号
}
常量defaultMessageQueue{
信息:[],
push:(num:number)=>{抛出新错误(“不使用默认值”);},
pop:()=>{抛出新错误(“不使用默认值”);}
}
export const MessageQueueContext=React.createContext(defaultMessageQueue);
在我提供的组件中:

const [messages, setmessages] = useState<number[]>([]);
//...
<MessageQueueContext.Provider value={{
  messages: messages,
  push:(num:number)=>{
    setmessages([...messages, num]);
  },
  pop:()=>{
    if(messages.length==0)return;

    const message = messages[-1];
    setmessages([...messages.slice(0, -1)]);
    return message;
  }
}}>
const[messages,setmessages]=useState([]);
//...
{
setmessages([…messages,num]);
},
流行音乐:()=>{
if(messages.length==0)返回;
常量消息=消息[-1];
setmessages([…messages.slice(0,-1)]);
返回消息;
}
}}>
现在,任何需要发送或接收消息的组件都可以使用上下文。
按预期推送消息。上下文将更改,所有使用上下文的组件将重新呈现。
但是弹出消息也会更改上下文并导致重新渲染。第二次重新渲染是浪费的,因为没有理由这样做


在使用useState和useContext进行状态管理的代码库中,是否有一种干净的方法来实现操作/消息/事件?

我不确定为什么不能将document.dispatchEvent(new CustomEvent())与关联的eventListener一起使用。
另外,如果是滚动问题,您可以使用refs滚动到视图中,因为您在爱奥尼亚(React Router)中使用路由,并且您可以在两个页面之间导航,您可以使用URL将参数传递到页面:

定义路由以具有可选路径参数。类似于
内容页/:节?

在ContentPage中,使用React Router的
useParams
获取参数(
部分
)。创建一个
useffect
,将
部分
作为唯一的更改依赖项。在第一次渲染时(或者如果
部分
更改),将调用滚动代码

const { section } = useParams();

useEffect(() => {
  // the code to jump to the section
}, [section]);

书签和内容页面一起显示?如果不是,您是否使用了react router之类的路由器?它们不会同时出现在屏幕上。这些页面是给一个路由器的,我用的是爱奥尼亚,所以这是他们的反应路由器。这很好,但这是一个相当小的解决方案。如果我不能使用路由传递消息怎么办?这与使用上下文和不重置消息队列(这也会导致只有一个重新提交器)没有什么区别还有其他解决方案,但是更改页面和滚动到页面中的某个位置应该基于路由。如果这些区域一起显示,则有其他使用上下文的解决方案,但没有使用有状态消息队列,因为上下文更改会重新引发每个页面。不是不可能,只是不是正确的工具。这是在反应。它将自己的合成事件系统修补到DOM中。在大多数情况下,React事件的行为类似于DOM事件,并修复了一些浏览器不一致的问题。但不支持自定义事件。这也使得不可能将react虚拟dom放入阴影dom(因为事件冒泡不起作用)。不幸的是,React事件系统是一个问题的兔子洞。
const { section } = useParams();

useEffect(() => {
  // the code to jump to the section
}, [section]);