Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.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 Hooks useReducer_Javascript_Reactjs_React Hooks_Context Api_Use Reducer - Fatal编程技术网

Javascript 仅当模式内容更改时防止模式重新呈现:React Hooks useReducer

Javascript 仅当模式内容更改时防止模式重新呈现:React Hooks useReducer,javascript,reactjs,react-hooks,context-api,use-reducer,Javascript,Reactjs,React Hooks,Context Api,Use Reducer,我的React应用程序中有一个父-子组件模态和模态内容 1) 我在App.js中创建了一个AppContext,用于在所有组件中全局访问它 const[state,dispatch]=useReducer(reducer,{modalOpen:false,content:[]) 要获取模态可见性的状态,请将其设置为打开/关闭 3) MyModalContent组件利用 const { state, dispatch } = useContext(AppContext); <ModalCo

我的React应用程序中有一个父-子组件模态模态内容

1) 我在App.js中创建了一个AppContext,用于在所有组件中全局访问它

const[state,dispatch]=useReducer(reducer,{modalOpen:false,content:[])

要获取模态可见性的状态,请将其设置为打开/关闭

3) My
ModalContent
组件利用

const { state, dispatch } = useContext(AppContext); 
<ModalContent data={state.content} />
  //Dispatch from the `ModalContent`
  dispatch({ type: 'UPDATE_CONTENT', data: 'newata' });
我已在
ModalContent
中设置了一些代码,以使用dispatch更新数据
content
属性,并且reducer存储已完全更新,并返回fresh/update:

 {modalOpen: true/false, content: updatedContentArray}
问题是:每当我通过
ModalContent
发送操作时,reducer返回(预期)完成状态,并且Modal在侦听state.modalOpen时重新打开自身

尝试不成功:我尝试在各个组件中专门提取所需的属性。但是
Modal
组件仍然会重新加载,即使只是更改了内容。有没有办法只监视特定的状态

如何通过仅重新提交
ModalContent
而不是
Modal


编辑:用我的模拟更新问题(工作)ModalContent本身的reducer代码和dispatch语句。

当内容更改时,
Modal
ModalContent
都被重新呈现的原因是因为这两个组件使用相同的上下文,并且当上下文值更改时,所有侦听上下文的组件都被重新呈现

解决这种重新渲染问题的一种方法是使用
多个上下文

 const modalContextVal = useMemo(() => ({ modalOpen: state.modalOpen, dispatch}), [state.modalOpen]);
   const contentContextVal = useMemo(() => ({ content: state.content, dispatch}), [state.content]);
   ....
   <ModalContext.Provider value={modalContextVal}>
      <ContentContext.Provider value={contentContextVal}>
      //BrowserRouter and Routes Definition
      </ContentContext.Provider>
    </ModalContext.Provider>
在ModalContent.js中

const {content, dispatch} = useContext(ContentContext);

正如@Shubham所说的,您必须将模态状态和模态内容分开

它可以在单独的上下文中完成,甚至可以使用简单的useState

示例片段

const{useReducer,createContext,useContext,useState,useffect,memo,usemo}=React;
const AppContext=createContext();
const reducer=(状态、操作)=>{
if(action.type==“toggleModal”){
返回{
……国家,
modalOpen:!state.modalOpen
}
}
返回状态;
}
const AppContextProvider=({children})=>{
const[state,dispatch]=useReducer(reducer,{modalOpen:false,content:[{id:1,value:'test'}]});
返回
{儿童}
}
常量模态=({children,modalOpen})=>{
const{state,dispatch}=useContext(AppContext);
console.log(“呈现模式”);
返回
{儿童}
}
const ModalContent=({data,onClick})=>{
log(“呈现模式内容”);
返回
{data.map(({id,value})=>{value})
接近
}
常量应用=()=>{
const{state,dispatch}=useContext(AppContext);
const{modalOpen,}=状态;
const[content,setContent]=useState([]);
const onClick=()=>{
分派({type:'toggleModal'});
}
返回
{useMemo(()=>{
console.log('render usemo');
返回
},[content])}
开放模态
}
ReactDOM.render(
,
document.getElementById('root'))
);
.modal{
背景:黑色;
位置:绝对位置;
排名:0;
左:0;
宽度:100%;
身高:100%;
不透明度:0;
z指数:-1;
过渡:所有.3s都很轻松;
}
.modal___关闭{
填充:.5rem1rem;
颜色:白色;
边框:1px纯白;
背景:透明;
光标:指针;
}
.模态-打开{
不透明度:1;
z指数:1;
}
.项目{
填充:1rem;
颜色:白色;
边框:1px纯白;
}


你能出示你的减速机和调度电话吗。还有一个问题是,Modal正在重新渲染,或者openModal错误地将modelOpen值设置为True。您可以使用
React.memo
增强
Modal
,使其成为一个已记忆的组件,如果
state.modalOpen
具有相同的值,则不会重新渲染。@ShubhamKhatri我已经添加了我的简化版本的减速机(工作)并在上面的代码段中添加了一个分派调用。OpenModel运行良好,正如我在关闭模式时所看到的,它会关闭,并且状态更新为false。好的,所以问题只是在只有内容更改时重新呈现模式组件?是的@ShubhamKhatriPerfect@shubham,工作得很有魅力,事实上,使用这种方法我甚至可以在单个组件中访问多个上下文(如果需要的话),无需担心重新排序,直到我专门更新了该状态!
 {modalOpen: true/false, content: updatedContentArray}
 const modalContextVal = useMemo(() => ({ modalOpen: state.modalOpen, dispatch}), [state.modalOpen]);
   const contentContextVal = useMemo(() => ({ content: state.content, dispatch}), [state.content]);
   ....
   <ModalContext.Provider value={modalContextVal}>
      <ContentContext.Provider value={contentContextVal}>
      //BrowserRouter and Routes Definition
      </ContentContext.Provider>
    </ModalContext.Provider>
const {modalOpen, dispatch} = useContext(ModalContext);
const {content, dispatch} = useContext(ContentContext);