我在这里有三个组成部分。 MainComponent包括其他两个。我想做的是,更改WebHeaderComponent中的select输入将刷新sidemenucomponent布局。但是当我尝试这样做时提示错误。
MainComponent
-> WebHeaderComponent
-> SideMenuComponent
MainComponent.tsx
const { Content } = Layout;
const MainComopnent: FunctionComponent = () => {
const [collapsed, setCollapsed] = useState(false);
const [menuList, setMenuList] = useState([]);
const services = useContext(ServicesContext);
const { MenuService } = services;
const { AuthenticationService } = services;
useEffect(() => {
const requestOption = {
method: "post",
body: JSON.stringify({
userCode: AuthenticationService.getUserModel().userCode,
roleId: AuthenticationService.getUserModel().roleId
})
}
MenuApi.getSideMenu(requestOption).then((result) => {
console.log(result);
const temp = MenuService.groupMenu(result);
setMenuList(temp);
});
}, []);
const value = { collapsed, setCollapsed };
return (
<SideMenuCollapsedContext.Provider value={value}>
<Layout className="layout">
<SideMenuComponent menuList={MenuService.getGroupMenu()}></SideMenuComponent>
<Layout className="site-layout">
<WebHeaderComponent></WebHeaderComponent>
<Content
className="site-layout-background"
style={{
margin: "24px 16px",
padding: 24,
minHeight: 280,
overflowY: "scroll",
}}
>
<AppRoutes />
</Content>
</Layout>
</Layout>
</SideMenuCollapsedContext.Provider>
);
};
export default MainComopnent;
WebHeaderComponent.tsx
const { Header } = Layout;
const WebHeaderComponent = () => {
const services = useContext(ServicesContext);
const { MenuService } = services;
const { AuthenticationService } = services;
const { UserInfoService } = services;
const [userRoleList, setUserRoleList] = useState<Array<any>>([]);
const {collapsed, setCollapsed} = useContext(SideMenuCollapsedContext);
const toggle = () => {
setCollapsed(!collapsed);
};
useEffect(() => {
const data = { userId: AuthenticationService.getUserModel().userId};
SysUserApi.searchSysUserRole(data).then((res) => {
setUserRoleList(res)
})
},[]);
const handleRoleChange = (selectedRoleId) => {
console.log('before: ' + selectedRoleId);
AuthenticationService.setRoleId(selectedRoleId);
console.log('after: ' + AuthenticationService.getUserModel().roleId)
}
return (
<Header className="site-layout-background" style={{ padding: 0 }}>
{React.createElement(
collapsed ? MenuUnfoldOutlined : MenuFoldOutlined,
{
className: "trigger",
style: { paddingLeft: "10px", fontSize: "20px" },
onClick: toggle,
}
)}
<div
style={{
float: "right",
paddingRight: "20px",
display: "flex",
alignItems: "center",
}}
>
<div><span>用戶:{AuthenticationService.getUserModel().userName}</span></div>
<div style={{ paddingLeft: "10px" }}>
<span>公司-角色:</span>
<Select
style={{ width: 120 }}
defaultValue={AuthenticationService.getUserModel().roleId}
onChange={handleRoleChange}
>
{userRoleList.map(item => (
<option
key={item.roleId}
value={item.roleId}
>
{item.roleName}
</option>
))}
</Select>
</div>
<div style={{ paddingLeft: "10px" }}>
<Button type="primary"> Sign Out </Button>
</div>
</div>
</Header>
);
}
export default WebHeaderComponent;
SideMenuComponent.tsx
const { Sider } = Layout;
const { SubMenu } = Menu;
const createSubMenus = (menuList): any => {
const menus: any = [];
for (const subMenuItem of menuList) {
if (subMenuItem.children && subMenuItem.children.length > 0) {
menus.push(
<SubMenu
key={subMenuItem.funcId}
title={
<span>
<MailOutlined />
<span className="fontWt">{subMenuItem.funcName}</span>
</span>
}
>
{createSubMenus(subMenuItem.children)}
</SubMenu>
);
} else {
menus.push(
<Menu.Item key={subMenuItem.funcId + subMenuItem.parentId}>
{subMenuItem.funcName}
<Link to={"/app" + subMenuItem.funcUrl} replace></Link>
</Menu.Item>
);
}
}
return menus;
};
const SideMenuComponent = ({ menuList }) => {
const value = useContext(SideMenuCollapsedContext);
const [subMenuList, setSubMenuList] = useState([]);
const { collapsed, setCollapsed } = value;
useEffect(() => {
setSubMenuList(createSubMenus(menuList));
}, [menuList]);
const handleCollapsed = (collapsed) => {
setCollapsed(collapsed);
};
return (
<Sider collapsible collapsed={collapsed} onCollapse={handleCollapsed}>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={["1"]}>
{/* <Menu.Item key="1" icon={<UserOutlined />}>
<Link to="/app/producttomms">Share Product to MMS</Link>
</Menu.Item>
<Menu.Item key="2" icon={<UserOutlined />}>
<Link to="/app/paymentorderanalyzer">Payment Order Analyzer</Link>
</Menu.Item>
<Menu.Item key="3" icon={<UserOutlined />}>
<Link to="/app/masterdatainitializer">Master Data Initializer</Link>
</Menu.Item> */}
{subMenuList}
</Menu>
</Sider>
);
};
export default SideMenuComponent;
在WebHeaderComponent中,下面有一个选择输入。我要做的是,一旦我从选择输入中更改了值,就在上下文中更新了一个值,我希望sideMenuComponent会被来自上下文的新菜单列表刷新。
但是,会提示错误消息。
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
答案 0 :(得分:0)
将您的状态提升到共同祖先(即父母)。
由于两者都可以访问该状态,因此您可以传递一个孩子的回调以更新父对象。
由于两个孩子共享相同的状态,因此又更新了另一个孩子。
export default function Parent() {
const [text, setText] = React.useState('not yet updated');
return (
<div>
<Child1 text={text} />
<Child2 onClick={setText} />
</div>
);
}
function Child1({ text }) {
return <p>{text}</p>
}
function Child2({ onClick }) {
return <button onClick={() => onClick('Child2 updated the state')}>Update</button>
}