请教父组件和子组件状态传递和刷新的问题?
大家好,组件 B.jsx 的代码如下,大概意思是它里面有一个按钮,可以打开菜单,也可以关闭菜单,切换菜单的打开和关闭
const B = ({ isMenuOpen, isMenuOpenCallback }) => {
const [localMenuOpen, setLocalMenuOpen] = useState(false);
const toggleMenu = (event) => {
setLocalMenuOpen(prevState => {
const newLocalMenuOpen = !prevState;
isMenuOpenCallback(newLocalMenuOpen);
return newLocalMenuOpen;
});
};
useEffect(() => {
setLocalMenuOpen(isMenuOpen);
}, [isMenuOpen]);
return (
<div>
<button className="preClass" onClick={toggleMenu} />
{localMenuOpen && (
<div className="menubar">这里是菜单的内容</div>
)}
</div>
)
}
export default B
组件 A.jsx 是组件 B 的父组件,即 B 组件被 A 组件引用,部分代码如下
import B from './B'
const handlePageClick = (e) => {
if (!e.target.closest('.menubar') {
setIsMenuOpen(false);=
}
};
useEffect(() => {
// listener
document.addEventListener('click', handlePageClick);
// remove
return () => {
document.removeEventListener('click', handlePageClick);
};
}, [isMenuOpen]);
return (
<B
otherHandler={() => otherHandler('news')}
isMenuOpen={isMenuOpen}
isMenuOpenCallback={(newMenuOpen) => setIsMenuOpen(newMenuOpen)} />
)
}
这些代码实现了当 B 组件中的菜单展开后,点击其父组件 A 中页面任何地方,都能关闭该菜单。但现在遇到的问题是总是有错误警告
Warning: Cannot update a component (A
) while rendering a different component (B
). To locate the bad setState() call inside B
请问这个该怎么修复呢?
或者说我的需求是点击 B 组件中的按钮可以打开关闭菜单,当菜单打开时,点击 A 组件的任何地方(菜单项除外),都能关闭菜单,有其它什么更合适的方法?
回复
1个回答
test
2024-06-21
状态都移到父组件即A上就可以了吧
// A.js
import React from 'react';
import B from './B.js';
function A() {
const [isMenuOpen, setMenuOpen] = React.useState(false);
const toggleMenu = () => {
console.log('toggle', isMenuOpen);
setMenuOpen(!isMenuOpen);
};
const closeMenu = (event) => {
if (event.target.closest('.menubar')) return;
console.log('closeMenu');
if (isMenuOpen) setMenuOpen(false);
};
return (
<div class="A" onClick={closeMenu}>
<B toggleMenu={toggleMenu} isMenuOpen={isMenuOpen} />
</div>
);
}
export default A;
// B.js
import React from 'react';
const B = ({ toggleMenu, isMenuOpen }) => {
return (
<div>
<button className="preClass" onClick={toggleMenu}>
Open{' '}
</button>
{isMenuOpen && <div className="menubar">这里是菜单的内容</div>}
</div>
);
};
export default B;
报warning应该是因为这段代码Cannot update a component (A) while rendering a different component (B).
setLocalMenuOpen
的callback
参数将会在rendering
的时候执行。isMenuOpenCallback(newLocalMenuOpen);
会触发A组件的更新。setLocalMenuOpen(prevState => { const newLocalMenuOpen = !prevState; isMenuOpenCallback(newLocalMenuOpen); return newLocalMenuOpen; });
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容