【问题标题】:ReactJS: How to maintain Index for Multiple ReadMore/ReadLess Buttons in LoopReactJS:如何在循环中维护多个阅读更多/阅读更少按钮的索引
【发布时间】:2021-01-20 01:41:26
【问题描述】:

我有一个数组 -

    var profiles = [
    {
        name: "Name1",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    },
    {
        name: "Name2",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    },
    {
        name: "Name3",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    },
    {
        name: "Name4",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
    }
];

我想截断描述字符串。只有前 25 个字符与“阅读更多”按钮一起可见。单击 Read More 时,状态应展开并应显示完整的字符串,单击 Read Less 时,段落应折叠。

问题是,当我点击 Read More 时,它触发点击循环中的所有段落,并且所有段落一起展开/折叠,而不是点击 ReadMore/ReadLess 的段落.

下面是我的代码

const ProfileGrid = (props) => {
    const [textRevealed, toggleText] = useState(false);
    const truncLength = 25;
    return (
        <>
          {props.profiles.map((profile,index) => (
              <p>{profile.name}</p>
              <p>{textRevealed ? profile.profile_description : 
                 profile.description.substring(0, truncLength)}...
                            <Button onClick={() =>  toggleText(!textRevealed)}>
                                 {textRevealed ? 'Read Less' : 'Read more'}
                            </Button>
                }</p>
        </>
   )

}

我不确定如何准确维护索引,因此当单击阅读更多时,只有单击的索引会展开/折叠。

谢谢

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    通过将collapse设置为一个独立的语句,将其转换为一个ReactNode,代码我是这样的。

    const truncLength = 25
    const ProfileGridItem = ({ name, description = '' }) => {
      const [isCollapse, setIsCollapse] = useState(false)
    
      return (
        <div>
          <p>{name}</p>
          <p>
            {description.substring(0, isCollapse ? truncLength : undefined)}...
            <Button onClick={() => setIsCollapse(isCollapse => !isCollapse)}>
              {isCollapse ? 'Read Less' : 'Read more'}
            </Button>
          </p>
        </div>
      )
    }
    
    const ProfileGrid = props => (
      <>
        {props.profiles.map((profile, index) => (
          <ProfileGridItem key={index} {...profile} />
        ))}
      </>
    )
    

    【讨论】:

    • 你的回答很好。我有同样的想法,但是 OP 的代码花了我太多时间才能在代码 sn-p 中重现 :(。无论如何,+1
    • 如果您能进一步帮助我添加 CSS 动画。基本上,我想在切换文本时添加缓入 300 秒动画。隐藏时不应占用空间。谢谢!
    【解决方案2】:

    最简单的方法是使用Component's power。

    意思是你应该break down把每一项相应的放入独立的组件中。

    因此,您可以轻松控制每个项目的状态。

    const [isShow, setShowHide] = React.useState(false); 
    

    const ProfileGrid = (props) => {
      return (
        <div>
          {props.profiles.map((profile, _) => (
            <ProfileItem {...profile} />
          ))}
        </div>
      );
    };
    
    const ProfileItem = (props) => {
      const truncLength = 25;
      const [isShow, setShowHide] = React.useState(false);
      return (
        <div>
          <p>{props.name}</p>
          <p>
            {" "}
            {isShow
              ? props.description
              : props.description.substring(0, truncLength)}{" "}
            ...
            <button onClick={() => setShowHide((previous) => !previous)}>
              {isShow ? "Read Less" : "Read more"}
            </button>
          </p>
        </div>
      );
    };
    
    var profiles = [
        {
            name: "Name1",
            description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        },
        {
            name: "Name2",
            description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        },
        {
            name: "Name3",
            description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        },
        {
            name: "Name4",
            description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        }
    ];
    ReactDOM.render(<ProfileGrid profiles={profiles} />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    
    
    <div id="root"></div>

    【讨论】:

    • 是的,这确实回答了我的问题。另外,感谢您提出将其分解并将其用作单个组件的标记。
    • 别忘了给我点赞,并通过单击勾号将我的答案标记为已解决,以便将来有读者,干杯^^! @Mshah
    猜你喜欢
    • 2021-08-22
    • 2020-09-23
    • 2015-06-22
    • 1970-01-01
    • 2020-11-21
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    相关资源
    最近更新 更多