我正在使用useState和useContext创建用于状态管理的React应用。到目前为止,这就像一个魅力,但现在我遇到了一个功能,该功能需要类似事件的内容:
比方说,有一个ContentPage可以渲染很多内容。用户可以滚动浏览并阅读内容。
还有一个BookmarkPage。单击书签将打开ContentPage并滚动到相应的内容。
此滚动到内容是一次性动作。理想情况下,我想在ContentPage中有一个使用ScrollTo(item)
事件的事件监听器。但是反应几乎阻止了所有事件的使用。 DOM事件无法捕获到虚拟dom中,并且无法创建自定义的合成事件。
此外,“打开内容XYZ”命令可以来自组件树中的许多部分(该示例并不完全适合我要实现的内容)。只会使树冒泡的事件并不能解决问题。
所以我想反应的方法是以某种方式用应用程序状态表示此事件?
我有一个解决方法,但是它很笨拙并且有问题(这就是为什么我要发布此问题的原因):
export interface MessageQueue{
messages: number[],
push:(num: number)=>void,
pop:()=>number
}
const defaultMessageQueue{
messages:[],
push: (num:number) => {throw new Error("don't use default");},
pop: () => {throw new Error("don't use default");}
}
export const MessageQueueContext = React.createContext<MessageQueue>(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;
}
}}>
现在,任何需要发送或接收消息的组件都可以使用上下文。
推送消息按预期工作。上下文发生更改,并且使用它的所有组件都重新呈现。
但是弹出一条消息也会更改上下文并导致重新渲染。因为没有理由这样做,所以第二次重新渲染被浪费了。
在使用useState和useContext进行状态管理的代码库中,是否存在一种干净的方法来实现动作/消息/事件?
答案 0 :(得分:1)
由于您在Ionic的router(响应路由器)中使用路由,并且在两个页面之间导航,因此可以使用URL将参数传递给页面:
定义路由以使其具有可选的路径参数。像content-page/:section?
在ContentPage中,使用React Router的section
获取参数(useParams
)。使用useEffect
创建一个section
作为唯一更改的依赖项。在第一次渲染(或如果section
更改)时,将调用滚动代码。
const { section } = useParams();
useEffect(() => {
// the code to jump to the section
}, [section]);
答案 1 :(得分:0)
我不确定为什么不能将document.dispatchEvent(new CustomEvent())与关联的eventListener一起使用。 另外,如果是滚动问题,则可以使用refs