ReactJS钩子-如何重新渲染其他组件
我这里有三个组件。主组件包括其他两个组件。我想做的是,WebHeaderComponent中选择输入的更改将刷新sidemenucomponent布局。但当我尝试这样做时,会出现错误提示ReactJS钩子-如何重新渲染其他组件,reactjs,typescript,react-hooks,Reactjs,Typescript,React Hooks,我这里有三个组件。主组件包括其他两个组件。我想做的是,WebHeaderComponent中选择输入的更改将刷新sidemenucomponent布局。但当我尝试这样做时,会出现错误提示 MainComponent -> WebHeaderComponent -> SideMenuComponent MainComponent.tsx const { Content } = Layout; const MainComopnent: FunctionComponent =
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;
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;
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;
提升状态
- 将你的状态提升到共同祖先(即父母)
- 由于两者都可以访问该状态,因此可以通过一个子级的回调来更新父级
- 这反过来会更新另一个子项,因为两个子项共享相同的状态
导出默认函数父函数(){
const[text,setText]=React.useState('尚未更新');
返回(
);
}
函数Child1({text}){
返回{text}
}
函数Child2({onClick}){
return onClick('Child2更新了状态')}>Update
}
您可能需要将状态从WebHeaderComponent
提升到两者最接近的共同祖先,并将一些属性值传递给SideMenuComponent
,以便它重新呈现。@Drewerese谢谢您的评论,您介意给我举个例子吗。我是一个新的反应,不知道真正需要做什么来实现你的目标。
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.
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>
}