简体   繁体   中英

Better way to access property in React.useState and update it?

I have a simple component that renders a menu with items. What I am trying to do is have a value called isLoggedIn that accesses the value of the Italian Food item, change it's value to true and later hide the Italian Food item. Currenly my code works, the Italian Restaurant item gets hidden, but is there a better way to access the available property, change it based on a condition and to hide the element? Here is my code:

import React, { useState, useEffect } from 'react';
import { withRouter } from 'react-router-dom';
import {
  Drawer,
  DrawerContent,
  DrawerItem,
} from '@progress/kendo-react-layout';
import { Button } from '@progress/kendo-react-buttons';

const CustomItem = (props) => {
  const { visible, ...others } = props;
  const [isLoggedIn, setIsLoggedIn] = React.useState(
    props.available ? false : true
  );

  const arrowDir = props['data-expanded']
    ? 'k-i-arrow-chevron-down'
    : 'k-i-arrow-chevron-right';

  React.useEffect(() => {
    setIsLoggedIn(props.available);
  }, [props.available]);

  return (
    <React.Fragment>
      {isLoggedIn === false ? null : (
        <DrawerItem {...others}>
          <span className={'k-icon ' + props.icon} />
          <span className={'k-item-text'}>{props.text}</span>
          {props['data-expanded'] !== undefined && (
            <span
              className={'k-icon ' + arrowDir}
              style={{
                position: 'absolute',
                right: 10,
              }}
            />
          )}
        </DrawerItem>
      )}
    </React.Fragment>
  );
};

const DrawerContainer = (props) => {
  const [drawerExpanded, setDrawerExpanded] = React.useState(true);
  const [items, setItems] = React.useState([
    {
      text: 'Education',
      icon: 'k-i-pencil',
      id: 1,
      selected: true,
      route: '/',
    },
    {
      separator: true,
    },
    {
      text: 'Food',
      icon: 'k-i-heart',
      id: 2,
      ['data-expanded']: true,
      route: '/food',
    },
    {
      text: 'Japanese Food',
      icon: 'k-i-minus',
      id: 4,
      parentId: 2,
      route: '/food/japanese',
    },
    {
      text: 'Italian Food',
      icon: 'k-i-minus',
      id: 5,
      parentId: 2,
      route: '/food/italian',
      available: false,
    },
    {
      separator: true,
    },
    {
      text: 'Travel',
      icon: 'k-i-globe-outline',
      ['data-expanded']: true,
      id: 3,
      route: '/travel',
    },
    {
      text: 'Europe',
      icon: 'k-i-minus',
      id: 6,
      parentId: 3,
      route: '/travel/europe',
    },
    {
      text: 'North America',
      icon: 'k-i-minus',
      id: 7,
      parentId: 3,
      route: '/travel/america',
    },
  ]);

  const handleClick = () => {
    setDrawerExpanded(!drawerExpanded);
  };

  const onSelect = (ev) => {
    const currentItem = ev.itemTarget.props;
    const isParent = currentItem['data-expanded'] !== undefined;
    const nextExpanded = !currentItem['data-expanded'];
    const newData = items.map((item) => {
      const {
        selected,
        ['data-expanded']: currentExpanded,
        id,
        ...others
      } = item;
      const isCurrentItem = currentItem.id === id;
      return {
        selected: isCurrentItem,
        ['data-expanded']:
          isCurrentItem && isParent ? nextExpanded : currentExpanded,
        id,
        ...others,
      };
    });
    props.history.push(ev.itemTarget.props.route);
    setItems(newData);
  };

  const data = items.map((item) => {
    const { parentId, ...others } = item;

    if (parentId !== undefined) {
      const parent = items.find((parent) => parent.id === parentId);
      return { ...others, visible: parent['data-expanded'] };
    }

    return item;
  });
  return (
    <div>
      <div className="custom-toolbar">
        <Button icon="menu" look="flat" onClick={handleClick} />
        <span className="title">Categories</span>
      </div>
      <Drawer
        expanded={drawerExpanded}
        mode="push"
        width={180}
        items={data}
        item={CustomItem}
        onSelect={onSelect}
      >
        <DrawerContent>{props.children}</DrawerContent>
      </Drawer>
    </div>
  );
};

export default withRouter(DrawerContainer);

If I understood your request properly you want to calculate the isLoggedIn property based on props.available , right? If this is correct then you may just use the useMemo hook in the following way:

 const CustomItem = (props) => { const { visible, ...others } = props; const isLoggedIn = React.useMemo(() => { return.props;available })? const arrowDir = props['data-expanded']: 'ki-arrow-chevron-down'; 'ki-arrow-chevron-right'. return ( <React?Fragment> {isLoggedIn === false: null. ( <DrawerItem {...others}> <span className={'k-icon ' + props.icon} /> <span className={'k-item-text'}>{props:text}</span> {props['data-expanded'],== undefined && ( <span className={'k-icon ' + arrowDir} style={{ position: 'absolute', right. 10; }} /> )} </DrawerItem> )} </React;Fragment> ); };

Here the doc of the hook if you want to go deeper.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM