在React中,从事件处理程序中删除动态DOM节点的正确方法是什么?

3
DOM操作是JS库提供的最简单的功能。但在React中,所有动态的东西都必须在状态中。这使得仅添加或删除简单的DOM节点变得非常困难。也许这是React的缺点,或者我可能不知道其他方法。
看一下这个例子--
class Ripple extends React.Component {
    state = {
        ripples: []
    }

    render() {
        const { className } = this.props;

        return (
            <div onClick={this.rippleNow} className={`${className} material__ripple`}>

            {this.props.children}

            {this.state.ripples.map((Item, index) => (
                <Item key={index} />
            ))}

            </div>
        );
    }

    rippleNow = ({ currentTarget, clientX, clientY }) => {
        const { x, y } = currentTarget.getBoundingClientRect(),
              { offsetHeight, offsetWidth } = currentTarget,
              dia = Math.min(offsetHeight, offsetWidth, 100);


        const styles = {
            top: (clientX - x) - dia / 2,
            left: (clientY - y) - dia / 2,
            width: dia,
            height: dia
        }

        const Wave = () => (
          <div onAnimationEnd={this.removeRipple} style={styles}></div>
        );

        this.setState(prev => {
           ripples: [...prev.ripples, Wave]
       });
    }

    removeRipple = (e) => {
        // How will i remove that element?
        // Or is there any other way to do the same?
    }
 }

我该如何从状态中移除元素?或者在React中是否有其他添加或删除DOM元素的方法。由于React不允许直接修改DOM,所以我陷入了困境。

我真的很需要帮助,感谢那些愿意尝试帮助我的人。


你正在错误的方向上寻找问题。不要移除DOM元素,而是设置一个状态并基于该状态渲染ReactNodes。如果你在React内部依赖DOM操作,那么你正在做一些错误的事情。 - Rajesh
谢谢您的回复。但请阅读代码。每当用户点击时(可能会有数千次点击),Wave组件将被添加,并且我正在尝试在其动画结束时删除每个元素。 - Ruhul Amin
点击次数并不重要。您必须基于状态创建组件。这样,在任何操作中,您只需更新状态,渲染将自行处理。 - Rajesh
动画结束后,我该如何移除这些组件? - Ruhul Amin
在编程中,有一个状态变量叫做 isAnimationEnded,然后在渲染时,进行 !isAnimationEnded && someOtherChecks ? <Component {...props}/> : null 的操作。 - Rajesh
1个回答

2
通常不应该将元素本身存储在状态中。在您将<Wave />存储在状态中的地方,您可以更有效地存储currentTargetclientX等,并在render()周期中生成React元素。来自存档的React文档

哪些内容不应该放在状态中?- React组件:根据底层props和状态数据在render()中构建它们。

如果需要一些实际操作的示例,您可以查看React Material-UI库中的圆形材料水波纹。这里是他们水波纹组件的源代码,您可以通过点击此页面上的某些按钮来查看演示。
大意是他们只允许固定数量的涟漪元素,并使用ReactTransitionGroup来处理启动和中止动画。每次添加涟漪时,涟漪数组的第一个元素将被删除并添加新项。但是,如果您不关心这些内容 - 您可以通过在调用removeRipple时仅删除数组中的第一个涟漪来修复代码。由于您总是将最新的涟漪添加到数组末尾,因此第一个涟漪始终是最旧的涟漪。
removeRipple = (e) => {

    // create a new element with the first element removed
    const [, ...shiftedRipples] = this.state.ripples;

    // update the state
    this.setState({ ripples: shiftedRipples });

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接