• 主页
  • 使用状态React动态更新样式属性

使用状态React动态更新样式属性

这是一个CodeSandox,如果你想看一下,代码可以在component > tabs > Tab.js - CodeSandox中找到

我有一个tabs组件,它计算父类Tab中所有选项卡的位置。然后,它根据提供的属性在选项卡active下正确定位一个元素Tabs-underline

我可以在加载时很好地设置元素的样式,但是,当我将鼠标悬停在选项卡上时,我希望样式适应悬停在上面的任何选项卡。我用更新this.state.sizesgetSizes()函数计算了这个值。

我遵循了这个教程,给你一个想法,它只是没有讨论如何处理当用户悬停在选项卡上时下划线的位置。YouTube Tutorial

但我就是想不出如何用正确的值动态更新它?

我认为我应该使用state来更新style属性。现在,我已经尝试过了,但是,我在初始加载时总是遇到这样的问题:每当我尝试从任何地方调用getUnderlineStyle(),而不是render,this.state.sizes都是一个空对象。我不认为在渲染函数中设置它有任何用处,因为当我悬停时,我应该如何处理它??

我完全不知所措,我被困在这里一整天,因为一些看似非常简单的事情,但再多的谷歌搜索也没有给我提供解决方案。我已经陷入了React的困境,所以这可能是一个非常简单的解决方案。

下面是我的组件,正如我所说的,在初始加载时工作良好,只是不确定如何实际实现悬停来更新状态值,然后更新Tabs-underline上的样式属性

我在下面的代码片段中留下了评论来帮助描述我的问题……

import React, { Component } from 'react';
import './Tabs.scss';

const transitionTime = 200;
const transitionStyle = `left ${transitionTime}ms, right ${transitionTime}ms`;

class Tabs extends Component {
   constructor(props) {
      super(props);
      this.state = {
         sizes: {},
         // Understand that this is what the style attribute value should be set to but how do I update it, it relies on this.state.sizes to be populated but cannot get it to a stage where it is populated???
         underLineStyle: {},
      };
      this.els = {};
      this.getSizes = this.getSizes.bind(this);
      this.getUnderlineStyle = this.getUnderlineStyle.bind(this);
   }

   componentDidMount() {
   // Is this the correct way to set the state???
      this.setState({
         sizes: this.getSizes()
      });
   }

   componentDidUpdate(prevProps, prevState) {
      if (prevProps.children !== this.props.children && prevProps.active !== this.props.active) {
         this.setState({
            sizes: this.getSizes()
         });
      }
   }

   getSizes() {
      const rootBounds = this.root.getBoundingClientRect();

      const sizes = {};

      Object.keys(this.els).forEach((key) => {
         const el = this.els[key];
         const bounds = el.getBoundingClientRect();

         const left = bounds.left - rootBounds.left;
         const right = rootBounds.right - bounds.right;

         sizes[key] = { left, right };
      });

      return sizes;
   }

   getUnderlineStyle() {
   // Calling this from within componentDidMount, this.state.sizes is empty?
   // Calling this directly on style attribute works but cannot manipulate on hover???
      if (this.props.active == null || Object.keys(this.state.sizes).length === 0) {
        return({left: '0', right: '100%'});
      }

      const size = this.state.sizes[this.props.active];

      return({
        left: `${size.left}px`,
        right: `${size.right}px`,
        transition: transitionStyle,
      });
   }

render() {

   return (
      <div className="Tabs" ref={el => this.root = el}>
         {React.Children.map(this.props.children, (child, i) => {
            return (
               <div
                  className={(child.key === this.props.active ? 'Tabs-item Tabs-itemActive' : 'Tabs-item') + (i === 0 ? ' Tabs-first' : i === (this.props.children.length - 1) ? ' Tabs-last' : null)}
                  onClick={() => {
                     this.props.onChange(child.key);
                  }}
                  onMouseEnter={/*something needs to go here, but what?*/}
                  ref={el => this.els[child.key] = el}
               >
                  {child}
               </div>
            );
         })}
         {this.props.underline ?
          // style attribute should be set to this.state.underlineStyle, but it currently an empty object?
            <div key={"Tabs-underline"} className="Tabs-underline" style={this.getUnderlineStyle()}></div>
            : null
         }
      </div>
   );
}
}

export default Tabs;

转载请注明出处:http://www.xjzlzx.com/article/20230527/1918202.html