繁体   English   中英

如何在 React with Hooks 中动态分配 map 内的 class

[英]How to dynamically assign class inside map in React with Hooks

我对 React 很陌生。 在我的gatsby站点的一个组件中,我有一个通过 map 动态生成的li列表。 此列表包含我通过 graphQL 从 WP 获得的帖子的分类。 我需要通过以下方式将特定的 class 分配给单击的li

  • 在第一次渲染时完全没有li ,然后
    • postlink-selected在点击的li
    • 在所有其他未点击的地方li post-link

使用下面的代码,我可以获得我需要的行为,但它在第二次点击时起作用。 看了几篇帖子我明白问题是我正在阅读以前的state,因此我需要第二次点击。 我也明白我可以通过设置useEffect来解决这个问题,我尝试过但不幸的是我无法正确设置useEffect以获得所需的行为,(我对useEffect的尝试没有在代码中报告)

在第二次点击的代码下方,如果不是很优雅,我很抱歉。 大多数代码用于其他内容,例如在子组件中保留一些 state,但根据评论,重点是li组件中的setActiveId

import React, { useState, useEffect } from 'react';
import { useStaticQuery, graphql, Link } from 'gatsby';
import parse from 'html-react-parser';

const query = graphql`
   query {
  allWpPost {
    group(field: categories___nodes___name) {
      fieldValue
      edges {
        node {
          title
          date(formatString: "MMMM DD, YYYY")
        }
      }
    }
  }
}`;

const CategoryBar = ({ children }) => {
  const { allWpPost } = useStaticQuery(query);
  const [activeId, setActiveId] = useState(null);
  const initialChoice = typeof window !== 'undefined' ? window.localStorage.getItem('choice') || 'projects' : null;
  const [choice, setChoice] = useState(initialChoice);
  useEffect(() => {
    window.localStorage.setItem('choice', choice);
  }, [choice, setChoice]);
  return (
    <div className="mainList">
      <div className="entryList">
        <div className="content">
        <ul>
          {allWpPost.group.map((category, i) => (
            <li
              key={category.fieldValue.toString()}
              className={activeId === null ? ' ' : ((activeId === i) ? 'post-linkselected' : 'post-link')}
              onClick={() => setActiveId(i)} //here I set the state but it is read on second click
            >
              <Link
                to={`/${category.fieldValue.replace(/\s+/g, '-').toLowerCase()}/${category.fieldValue.replace(/\s+/g, '-').toLowerCase()}posts`}
                onClick={() => setChoice(parse(category.fieldValue.replace(/\s+/g, '-').toLowerCase()))}
                state={{ choice: parse(category.fieldValue.replace(/\s+/g, '-').toLowerCase()) }}
              >
                {category.fieldValue}
              </Link>
            </li>
          ))}
        </ul>
        </div>
      </div>
      {children}
    </div>
  );
};

export default CategoryBar;

非常感谢您的帮助

我认为您正在寻找的是 gatsby Link 的 activeClassName。 使用此道具 gatsby 会自动将您选择的类名(在您的情况下为 postlink-selected)添加到链接组件: https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/#add-custom -styles-for-the-current-active-link

我不确定您使用 localStorage 的目的是什么,但我猜您正在尝试默认导航到先前保存的类别页面; 如果是这种情况,仅在链接上设置活动 class 是不够的,您需要实际将用户导航到该页面。

如果你能澄清你的意图,我可能会提供进一步的帮助。

经过进一步调查后,我的问题似乎是由于在渲染子组件时父级重新渲染应用初始 state 'null' in const [activeId, setActiveId] = useState(null); . 这覆盖了由onClick={() => setActiveId(i)设置的 state 并应用了空白 class。 在第二次单击相同的li时,不会发生重新渲染,并且 state 已正确更新,并按预期应用了两个类。 有关如何解决此行为的任何见解? 非常感谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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