মেনু একটি সঠিক সূচক ডিভ খুলছে না


11

ছেলে আমি সমস্যার মুখোমুখি। আমার কাছে একটি 2-মাত্রিক ডেটা রয়েছে। ডেটাতে একটি নেস্টেড কাঠামো রয়েছে যার মধ্যে লিঙ্ক রয়েছে।

const data = [
  // First Div Panel 
  [
    {
      id: 1,
      url: "/services",
      title: "Services"
    },
    {
      id: 2,
      title: "Products",
      children: [
        {
          id: 3,
          url: "/themes-templates",
          title: "Themes & Templates"
        },
        {
          id: 4,
          url: "/open-source",
          title: "Open Source"
        },
        {
          id: 5,
          url: "/solutions",
          title: "Solutions"
        }
      ]
    },
    {
      id: 6,
      url: "/work",
      title: "Work",
      children: [
        {
          id: 7,
          url: "/methodology",
          title: "Methodology",
          children: [
            {
              id: 8,
              url: "/agile",
              title: "Agile",
              children: [
                {
                  id: 9,
                  url: "/scrum",
                  title: "Scrum"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      id: 10,
      url: "/contact-us",
      title: "Contact Us"
    }
  ],
  // Second Div Panel which contains children of second list item
  [
    {
      id: 3,
      url: "/themes-templates",
      title: "Themes & Templates"
    },
    {
      id: 4,
      url: "/open-source",
      title: "Open Source"
    },
    {
      id: 5,
      url: "/solutions",
      title: "Solutions"
    }
  ],
  // Third Div Panel which contains children of third list item
  [
    {
      id: 7,
      url: "/methodology",
      title: "Methodology",
      children: [
        {
          id: 8,
          url: "/agile",
          title: "Agile",
          children: [
            {
              id: 9,
              url: "/scrum",
              title: "Scrum"
            }
          ]
        }
      ]
    }
  ],
  // Fourth Div Panel contains the children of the 3rd sub list item
  [
    {
      id: 8,
      url: "/agile",
      title: "Agile",
      children: [
        {
          id: 9,
          url: "/scrum",
          title: "Scrum"
        }
      ]
    }
  ],
  // Fourth Div Panel contains the children of the 3rd sub sub list item
  [
    {
      id: 9,
      url: "/scrum",
      title: "Scrum"
    }
  ]
];

আমার কাজটি হ'ল দ্বি-মাত্রিক ডেটা ব্যবহার করা এবং এতে একটি মোবাইল মেনু তৈরি করা reactযাতে এতে একটি পুশ প্যানেলের মতো কাঠামো থাকে।

তবুও, আমি এটি তৈরি করার চেষ্টা করি। আমি যা করেছি তা হ'ল আমি প্রতিটি উপ-অ্যারে পৃথক প্যানেল হিসাবে বিবেচনা করি div। প্রথমে সাব-অ্যারে আইটেমগুলি রুট প্যানেলে বিবেচনা করা হবে যা ডিফল্টরূপে দৃশ্যমান। যদি কোনও আইটেমটির কোনও childrenসম্পত্তি থাকে তবে এর অর্থ nextসেই তালিকা আইটেমটিতে গতিশীলভাবে বোতাম তৈরি করা হয়েছে। আমরা যখন এই বোতামটিতে ক্লিক করব তখন is-visibleএটি প্যানেলে একটি শ্রেণি যুক্ত করবে । তবে, প্রশ্নটি কীভাবে প্যানেলটি সেই বোতামের ক্লিকের সাথে যুক্ত তা ট্র্যাক করবে ? আমি এর সাথে একটি রাজ্য ব্যবহার করার চেষ্টা করি activeIdএবং prevIdতবে আমার সূচক সঠিকভাবে কাজ করছে না এবং একটি সঠিক প্যানেল খুলছে না। আপনি ক্রোম ইন্সপেক্টর প্যানেলে আমার সমাধানটি পরীক্ষা করতে পারেন। আমি এর প্রশংসা করি যদি আপনি আমাকে বলছেন আমি কী ভুল করছি?

আমার কোড স্যান্ডবক্স লিঙ্ক

কোড:

// Get a hook function
const {useState} = React;

//#region Data
const data = [
  // First Div Panel
  [
    {
      id: 1,
      url: "/services",
      title: "Services"
    },
    {
      id: 2,
      title: "Products",
      children: [
        {
          id: 3,
          url: "/themes-templates",
          title: "Themes & Templates"
        },
        {
          id: 4,
          url: "/open-source",
          title: "Open Source"
        },
        {
          id: 5,
          url: "/solutions",
          title: "Solutions"
        }
      ]
    },
    {
      id: 6,
      url: "/work",
      title: "Work",
      children: [
        {
          id: 7,
          url: "/methodology",
          title: "Methodology",
          children: [
            {
              id: 8,
              url: "/agile",
              title: "Agile",
              children: [
                {
                  id: 9,
                  url: "/scrum",
                  title: "Scrum"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      id: 10,
      url: "/contact-us",
      title: "Contact Us"
    }
  ],
  // Second Div Panel
  [
    {
      id: 3,
      url: "/themes-templates",
      title: "Themes & Templates"
    },
    {
      id: 4,
      url: "/open-source",
      title: "Open Source"
    },
    {
      id: 5,
      url: "/solutions",
      title: "Solutions"
    }
  ],
  // Third Div Panel
  [
    {
      id: 7,
      url: "/methodology",
      title: "Methodology",
      children: [
        {
          id: 8,
          url: "/agile",
          title: "Agile",
          children: [
            {
              id: 9,
              url: "/scrum",
              title: "Scrum"
            }
          ]
        }
      ]
    }
  ],
  // Fourth Div Panel
  [
    {
      id: 8,
      url: "/agile",
      title: "Agile",
      children: [
        {
          id: 9,
          url: "/scrum",
          title: "Scrum"
        }
      ]
    }
  ],
  // Fifth Div Panel
  [
    {
      id: 9,
      url: "/scrum",
      title: "Scrum"
    }
  ]
];
//#endregion Data

//#region Component


const PanelMenu = props => {
  const { title } = props;

  const [items, setItems] = useState(data);

  // Title Header of the Panel
  const [headerTitle, setHeaderTitle] = useState(title ? title : "");
  // Previous Title Header of the Panel
  const [prevHeaderTitle, setPrevHeaderTitle] = useState(title ? title : "");
  // ActiveIndex => 0 means by default master-panel is active
  const [activeId, setActiveId] = useState(0);
  // PreviousIndex
  const [prevId, setPrevId] = useState(0);

  const handlePanelBtn = (newTitle, index, prevIndex) => {
    // Title Checking
    const titleProp = title ? title : "";
    const prevTitle = index === 0 ? titleProp : headerTitle;
    // SetStates
    setPrevHeaderTitle(prevTitle);
    setHeaderTitle(newTitle);
    setActiveId(index);
    setPrevId(prevIndex);
  };

  const panelRenderer = () => {
    const panelsJSX = [];
    for (let i = 0; i < items.length; i++) {
      let childItemIndex = i;
      const panels = (
        <div
          key={i}
          id={i === 0 ? "p__master" : `p__student-${i}`}
          className={
            childItemIndex === activeId
              ? "p__panel is-visible"
              : "p__panel is-hide"
          }
        >
          <ul>
            {items[i].map((item, index) => {
              // It means it have children
              if (item.children && item.children.length > 0) {
                childItemIndex++;
                return (
                  <li key={item.id} className="p-next">
                    {item.url ? (
                      <a href={item.url} className="p-link">
                        {item.title}
                      </a>
                    ) : (
                      <div className="p-link">{item.title}</div>
                    )}
                    <button
                      type="button"
                      className="p-next__btn"
                      data-id={`#p__student-${childItemIndex}`}
                      onClick={() => handlePanelBtn(item.title, index, prevId)}
                    >
                      <span>&gt;</span>
                    </button>
                  </li>
                );
              } else {
                return (
                  <li key={item.id}>
                    <a href={item.url} className="p-link">
                      {item.title}
                    </a>
                  </li>
                );
              }
            })}
          </ul>
        </div>
      );

      panelsJSX.push(panels);
    }
    return panelsJSX;
  };

  const renderer = () => {
    if (items && items.length > 0) {
      return (
        <div className="p">
          <div className="p__wrap">
            {/* Panel Actions => Header */}
            <div className="p__actions">
              {/* Previous Button */}

              {activeId !== 0 && (
                <button
                  type="button"
                  className="p-action__btn left"
                  onClick={() =>
                    handlePanelBtn(prevHeaderTitle, prevId, prevId)
                  }
                >
                  <span>&lt;</span>
                </button>
              )}

              {/* Title */}
              {headerTitle && (
                <div className="p-action__title">{headerTitle}</div>
              )}

              {/* Close Button */}
              <button type="button" className="p-action__btn right">
                <span>×</span>
              </button>
            </div>
            {/* Panel children Wrapper */}
            <div className="p__children">{panelRenderer()}</div>
          </div>
        </div>
      );
    }
  };
  return <React.Fragment>{renderer()}</React.Fragment>;
};

//#endregion Component



// Render it
ReactDOM.render(
  <PanelMenu title="Menu" />,
  document.getElementById("root")
)
<style>

*,:before,:after {
    box-sizing: border-box;
}


.p__wrap {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 320px;
    background-color: #fff;
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
    z-index: 1;
    color: #333;
    overflow-x: hidden;
}

.p__actions {
    position: relative;
    padding: 14px;
    min-height: 54px;
    border-bottom: 1px solid #dcdcdc;
}

.p-action__title {
    text-align: center;
    color: #333;
    text-transform: uppercase;
    font-weight: 700;
}

.p-action__btn {
    position: absolute;
    width: 54px;
    height: 54px;
    top: 0;
    right: 0;
    font-size: 16px;
    color: #333;
    border: none;
    cursor: pointer;
}

.left {
    left: 0;
}

.right {
    right: 0;
}

.p__children {
    position: relative;
    background-color: #fff;
    overflow: hidden;
    height: calc(100% - 54px);
}

.p__panel {
    overflow-x: hidden;
    overflow-y: auto;
    position: absolute;
    transform: translateX(100%);
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 0;
    transition: transform 0.2s ease 0s;
}

.p__panel.is-visible {
    transform: translateX(0);
    z-index: 1;
}

.p__panel.is-hide {
    opacity: 0;
    visibility: hidden;
}

.p__panel > ul {
    margin: 0;
    padding: 0;
}
.p__panel > ul > li {
    list-style: none;
    border-bottom: 1px solid #dcdcdc;
}
.p__panel > ul > li > .p-link {
    color: #333;
    display: block;
    line-height: 22px;
    font-size: 14px;
    padding: 14px 24px;
    background-color: transparent;
    cursor: pointer;
}



.p__panel > ul > li > .p-link:hover {
   background-color: #dcdcdc;
}

.p-next {
    position: relative;
}

.p-next__btn {
    position: absolute;
    padding: 14px 16px;
    font-size: 16px;
    line-height: 22px;
    top: 0;
    right: 0;
    background-color: rgb(240,240,240);
    color: #333;
    border: none;
    border-left: 1px solid #dcdcdc;
    cursor: pointer;
}

</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

উত্তর:


3

আমি এগিয়ে গিয়েছিলাম এবং নিম্নলিখিত কোড স্যান্ডবক্সে আপনার কোডটিকে একটি কার্যকারী উদাহরণে রূপান্তরিত করেছি: https://codesandbox.io/s/panel-menu-hfrmx?foutsize=14&hidenavication=1&theme=dark

এটি প্রথমে অনেকগুলি পরিবর্তনের মতো মনে হতে পারে, তাই আমি কিছুটা বিস্তারিতভাবে বর্ণনা করব:

  • আমি মেনু শিরোনাম এবং মেনু আইটেম তালিকাটি তাদের পুনরায় পুনঃব্যবহারের অনুমতি দিয়ে তাদের নিজস্ব উপাদানগুলিতে বের করেছি
  • আমি আপনার ডেটা কাঠামোটি আবার লিখেছি, যাতে আপনার মেনু আইটেমগুলি দু'বার বা এমনকি তিনবার সংজ্ঞায়িত করার প্রয়োজন না হয়। এই কাঠামোটি সমতল, যা আপনাকে এটি সহজেই কোনও ডাটাবেজে সংরক্ষণ করতে দেয় যা আপনি এটি চান।

আমি এটা পরীক্ষা করব।
জন চাকস

প্রথমে সঠিক প্যারেন্টের সাথে অ্যারে সমতল করা indexএবং তারপরে এই মেনুটি তৈরি করা একটি দুর্দান্ত ধারণা । উপায় দ্বারা, তথ্য একটি বাহ্যিক API থেকে আসছে। তবে আপনার পদ্ধতির ব্যবহার সমস্যা সমাধানে সত্যই সহায়ক।
জন চাকস

এটি সহায়ক যে প্রশংসা করুন। যদি এটি আপনার সমস্যার সমাধান করে তবে আপনি এটি স্বীকৃত হিসাবে চিহ্নিত করতে পারেন। অন্যথায়, আপনার আরও কিছু তথ্যের প্রয়োজন হলে আমাকে জানান।
ওয়াউটার রাইটল্যান্ড

জাভাস্ক্রিপ্টে শ্রেণিবদ্ধ তথ্য কাঠামো সংরক্ষণ করার জন্য সর্বোত্তম পন্থা কোনটি? আমাদের কি শিশুদের এক-মাত্রিক অ্যারের ভিতরে বাসা বাঁধতে হবে বা প্যারেন্ট আইডির রেফারেন্স পাওয়া জিনিসগুলি দিয়ে অ্যারে সমতল করতে হবে? আপনি কি পরামর্শ দিয়েছেন?
জন চাকস

এটি নির্ভর করে ব্যবহারের ক্ষেত্রে। আপনি যদি নিশ্চিত হন যে আপনি একবারে ডেটা ব্যবহার করবেন এবং যদি পারফরম্যান্স সমালোচনা হয়, তবে এটির স্তরক্রমিক আকারে এটি সংরক্ষণ করার জন্য কিছু বলার আছে। তবে, যদি আপনি একই উপাত্তটি বিভিন্ন উপায়ে ব্যবহার করতে পারেন তবে আমি মনে করি এটি যতটা সম্ভব ফ্ল্যাট সংরক্ষণ করা প্রায়শই সহজ।
ওয়াউটার রাইটল্যান্ড 20

1

আমার মনে হয় আপনার দরকার আছে

handlePanelBtn(item.title, childItemIndex, prevId)

পরিবর্তে

handlePanelBtn(item.title, index, prevId)

https://codesandbox.io/s/panel-menu-2uwxo


আপনার কোডস্যান্ডবক্সে আমি productsতালিকা-আইটেম nextবোতামটি ক্লিক করি। এটি productsতালিকার আইটেমের শিশুদের খুলছে না ।
জন চাকস

0

প্যানেল দেখানোর আপনার যুক্তিটি সহজ করার জন্য আমি প্রসঙ্গটি এপিআই দিয়ে এটি করেছি।

PanelContext নামে পরিচিতি তৈরি করুন যার প্যানেল অ্যারে রয়েছে যা বর্তমান প্যানেলটি প্রদর্শন করতে এবং মেনুতে ফিরে যেতে ব্যবহার করা যেতে পারে।

import React from "react";

export const PanelContext = React.createContext();
export function PanelProvider({ children }) {
  const [currentPanel, setCurrentPanel] = React.useState([0]);
  const addItemToPanel = item => setCurrentPanel(prev => [item, ...prev]);
  const goBack = () => setCurrentPanel(prev => prev.slice(1));
  return (
    <PanelContext.Provider
      value={{
        currentPanel: currentPanel[0],
        setCurrentPanel: addItemToPanel,
        goBack
      }}
    >
      {children}
    </PanelContext.Provider>
  );
}

এবং তৈরি প্যানেল উপাদান যা পুনরাবৃত্তভাবে সমস্ত প্যানেল এবং শো প্যানেল তৈরি করবে যা প্রসঙ্গে মানের ভিত্তিতে সক্রিয় রয়েছে।

const Panel = ({ items, id, title }) => {
  const { currentPanel, setCurrentPanel, goBack } = React.useContext(
    PanelContext
  );
  const panels = [];
  return (
    <>
      <div
        className={id === currentPanel ? "p__wrap visible" : " p__wrap hidden"}
      >
        <h2>
          {title && <button onClick={goBack}>{"<"}</button>} {title || "Menu"}{" "}
        </h2>
        <div className="p__panel">
          <ul>
            {items.map(item => {
              if (item.children)
                panels.push(
                  <Panel
                    title={item.title}
                    id={item.id}
                    items={item.children}
                  />
                );
              return (
                <React.Fragment key={item.id}>
                  <li>
                    {item.title}
                    {item.children && (
                      <button
                        onClick={() => {
                          setCurrentPanel(item.id);
                        }}
                      >
                        {">"}
                      </button>
                    )}
                  </li>
                </React.Fragment>
              );
            })}
          </ul>
        </div>
      </div>
      {panels}
    </>
  );
};
export const PanelMenu = props => {
  return (
    <PanelProvider>
      <Panel items={data} id={0} />
    </PanelProvider>
  );
};

আমি আপনার সিএসএস ভঙ্গ করেছি।

এবং গভীরভাবে নেস্টেড বাচ্চাদের সাথে একটিমাত্র বস্তু ব্যবহার করে।

এখানে কোডস্যান্ডবক্স কাজ করছে: https://codesandbox.io/s/panel-menu-c871j


উত্তরের জন্য ধন্যবাদ সত্য যে প্রশংসা।
জন চাকস

আপনাকে স্বাগতম!
অমিত চৌহান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.