Guys I'm working on a project now and I have a component that is returned by antd Menu
item. It has 4 components: Home
, Username
, Login
, and Register
:
const items = [
{
label: <Link to='/'>Home </Link>, //- {JSON.stringify(user)}
key: 'home',
icon: <AppstoreOutlined />,
},
{
label: 'Username',
key: 'SubMenu',
icon: <SettingOutlined />,
children: [
{
label: 'Option 1',
key: 'setting:1',
},
{
label: 'Option 2',
key: 'setting:2',
},
{
label: <item onClick={logout}>Logout</item>,
key: 'setting:3',
icon: <LogoutOutlined />
},
],
},
{
label: <Link to='/register'>Register</Link>,
key: 'register',
icon: <UserAddOutlined />,
style: { marginLeft: 1030}, // problem: hard-coded margin
},
{
label: <Link to='/login'>Login</Link>,
key: 'login',
icon: <UserOutlined />,
style: { marginLeft: 'auto'},
},
];
useEffect(() => {
if (user) { // "user" is an object returned by userSelector
items.splice(2, 2);
}
}, [user]);
console.log(items);
return <Menu onClick={handleClick} selectedKeys={[current]} mode="horizontal" items={items} />;
As you can see, I'm useing a useEffect
hook here. If the user is not logged in (so user === null
), then the if statements in useEffect
will not be executed; otherwise the Login
and Register
components in array items
will be removed and hided, and only the first 2 are left.
From console.log(items);
we can see what items
is like currently. When a user is logged in, it does have only two components:
However we can still see Login
and Register
are there in such a circumastance:
So why do js and react render removed components?
CodePudding user response:
You need to use "useState" hook to make the UI update, in you example, the items will be updated, but the UI will not update.
import { useState } from 'react'
const [items, setItems] = useState([
{
label: <Link to='/'>Home </Link>, //- {JSON.stringify(user)}
key: 'home',
icon: <AppstoreOutlined />,
},
{
label: 'Username',
key: 'SubMenu',
icon: <SettingOutlined />,
children: [
{
label: 'Option 1',
key: 'setting:1',
},
{
label: 'Option 2',
key: 'setting:2',
},
{
label: <item onClick={logout}>Logout</item>,
key: 'setting:3',
icon: <LogoutOutlined />
},
],
},
{
label: <Link to='/register'>Register</Link>,
key: 'register',
icon: <UserAddOutlined />,
style: { marginLeft: 1030}, // problem: hard-coded margin
},
{
label: <Link to='/login'>Login</Link>,
key: 'login',
icon: <UserOutlined />,
style: { marginLeft: 'auto'},
},
]);
useEffect(() => {
if (user) { // "user" is an object returned by userSelector
setItems((items) => {
items.splice(2, 2);
return items;
}
}
}, [user]);
CodePudding user response:
If you need the re render to be happened. You can store the array in a state. If you store the array in normal javascript variable. React will not re render the component. Try like I given below,
const [items, setItems] = useState([
{
label: <Link to='/'>Home </Link>, //- {JSON.stringify(user)}
key: 'home',
icon: <AppstoreOutlined />,
},
{
label: 'Username',
key: 'SubMenu',
icon: <SettingOutlined />,
children: [
{
label: 'Option 1',
key: 'setting:1',
},
{
label: 'Option 2',
key: 'setting:2',
},
{
label: <item onClick={logout}>Logout</item>,
key: 'setting:3',
icon: <LogoutOutlined />
},
],
},
{
label: <Link to='/register'>Register</Link>,
key: 'register',
icon: <UserAddOutlined />,
style: { marginLeft: 1030}, // problem: hard-coded margin
},
{
label: <Link to='/login'>Login</Link>,
key: 'login',
icon: <UserOutlined />,
style: { marginLeft: 'auto'},
},
]);
useEffect(() => {
if (user) { // "user" is an object returned by userSelector
setItems(items.splice(2, 2));
}
}, [user]);
console.log(items);
return <Menu onClick={handleClick} selectedKeys={[current]} mode="horizontal" items={items} />;