как рассчитать ширину всех li в react?

#javascript #reactjs #react-router

#javascript #reactjs #react-маршрутизатор

Вопрос:

У меня есть один ul , и внутри него у меня есть .У меня есть li . ul max-width 400 Я хочу показать только несколько li ‘ (до 400px ) после того, что я хочу показать More link .когда пользователь нажимает на more link него, отображается оставшееся li . поэтому я хочу рассчитать ширину li элемента, чтобы я мог разбить свои li (до большего количества li и оставшегося li). можем ли мы рассчитать li и сравнить всегда общую li ширину с 400px тем, достигнута она или нет.

вот мой код https://codesandbox.io/s/dazzling-stonebraker-usly9?file=/src/styles.css

Я могу получить ширину parent (400 пикселей), но мне нужна ширина всех li присутствующих внутри ul

 export default function App() {
  const [activeIndex, setActiveIndex] = useState(0);
  const navRef = useRef();
  useEffect(() => {
    if (navRef) {
      console.log(navRef.current.offsetWidth);
    }
  }, []);
  return (
    <div className="cls">
      <ul className="nav" ref={navRef}>
        {links.map(({ text, url }, index) => {
          return (
            <li
              key={index}
              className={[`${index === activeIndex ? "active" : ""}`].join(" ")}
            >
              <a data-target="rc64panel_2" href={url}>
                <span>{text}</span>
              </a>
            </li>
          );
        })}
      </ul>
    </div>
  );
}
 

Я вычисляю ширину, потому что хочу знать, сколько элементов я покажу раньше, а остальные я хочу знать во всплывающем окне
Спасибо @KS . updating
Пример
Давайте возьмем пример, у меня 5 li. используя css, это как 3 li. как я узнаю, что осталось 2? позвольте взять, я хочу показать оставшийся элемент во всплывающем окне

Ответ №1:

Вы можете сделать это с помощью pure CSS и просто заменить класс, когда вам нужно.

 .cls {
   max-width: 400px;
   overflow-x: hidden;
}
 

И когда вам больше не нужен этот класс (при нажатии кнопки), вы просто удаляете его.

 // you store the class name in the state
const [classes, setClasses] = useState('cls')
// 
const handleShowMore = () => {
  setClasses('') // or anything else
}
...

return <div>
 <div className={classes}>your li go here</div>
 <button onClick={handleShowMore}>show more</button>
</div>
 

Обновить
Вы можете получить скрытые, обратившись к ссылке, которая у вас уже есть.

 [...navRef.current.children].forEach((item, index) => {
  item.offsetWidth // will get you the li width
})
 

теперь вы можете либо получить индексы элементов, либо переместить их в узел, в котором вы хотите их отобразить (div в модальном) с помощью appendChild .

Комментарии:

1. @ks спасибо за ответ. но как узнать, сколько осталось элементов

2.давайте возьмем пример, который у меня есть 5 li's . используя css, это как 3 li . как я узнаю, что осталось 2? позвольте, я хочу показать оставшийся элемент во всплывающем окне.

3. Вы должны обновить вопрос с учетом этих требований.

4. вот почему я пытаюсь рассчитать ширину, чтобы я мог принимать переменную в состоянии, пока она не отобразится. и оставшееся я покажу во всплывающем окне. конечно, я обновлю это

5. @Ks это возможно или?

Ответ №2:

Вы могли бы получить ширину каждого li, прежде чем помещать их в dom, суммировать их и при достижении порогового значения скрывать остальные элементы, пока пользователь не нажмет на дополнительную ссылку

Самый простой подход

 const links = [
  {
    text: "Technology",
    url: "placeholder.html"
  },
  {
    text: "Beauty",
    url: "placeholder.html"
  },
  {
    text: "Construction",
    url: "placeholder.html"
  },
  {
    text: "Manufactoring",
    url: "placeholder.html"
  },
  {
    text: "Transportation",
    url: "placeholder.html"
  },
  {
    text: "Real Estate",
    url: "placeholder.html"
  },
];

const { useRef, useState, useEffect } = React;



const App = () => {
  const [clickedMore, setClickMore] = useState(false);
  const onClick = () => setClickMore(true);
  
  const renderListItems = function*() {
    const widthThreshold = 200;
    let totalWidth = 0;
    let index = 0;
    for(const link of links) {
     
     const test = document.createElement("li");
     test.textContent = link.text;
     test.style.visibility = 'hidden';
     test.style.position = 'absolute';
     document.body.appendChild(test);
     const offsetWidth = test.offsetWidth;
     test.parentNode.removeChild(test);
     
     const style = {
      display: "list-item",
     }
     
     if(!clickedMore amp;amp; totalWidth   offsetWidth > widthThreshold) {
      style.display = "none";
     }
     
     totalWidth  = offsetWidth;
     
     yield (<li style={style} key={index}>{link.text}</li>);
     
     index  ;
     
    }
  }

    return <div><ul className="nav">
      {[...renderListItems()]}
    </ul>
    {clickedMore ? null : <div>
      <button onClick={onClick}>More link</button>
    </div>}
  </div>;
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
); 
 * {
  padding: 0;
  margin: 0;
  list-style: none;
}
.cls {
  max-width: 400px;
}
.nav {
  display: flex;
  width: 100%;
  position: relative;
  padding-right: calc(44px - 0.9em);
}

.nav > li {
  flex-grow: 1;
} 
 <script src="https://unpkg.com/react/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js"></script>

    <div id="root"></div>