当状态改变时,针不会更新

时间:2017-04-19 01:30:03

标签: javascript reactjs svg

我有一个温度计svg,我希望与它进行某种互动。交互将按照用户提供的值移动针。可以从游侠提供该值,并且应该通过移动针来更新温度计。

我在webpack bin中创建了一个示例,因此您可以在此处查看演示https://www.webpackbin.com/bins/-Khv7qwzOc5OlYE9UY-1

这就是我所做的

componentDidMount(){
  this.animationH.setAttribute('from', this.animationH.getAttribute('to'));
  this.animationH.setAttribute('to', this.state.value);
  this.animationY.setAttribute('from', this.animationY.getAttribute('to'));
  this.animationY.setAttribute('to', this.state.value);
}

handleChange(event) {
  this.setState({ value: event.target.value });
}

render() {
  const {value} = this.state;

  return (
    <div>
      <input 
        type="range" 
        min="1" 
        max="100" 
        step="1" 
        onChange={(event) => this.handleChange(event)}
      />
      {value ? value : ''}
      <svg width="133px" height="350px" viewBox="0 0 133 1113" version="1.1" xmlns="http://www.w3.org/2000/svg">
        <rect id="Rectangle-2" stroke="#979797" strokeWidth="2.132" fill="#C20C0C" filter="url(#filter-1)" x="56.8899994" y="735" width="18" height="200">
        <animate 
          attributeName="height"
          from="0"
          to="200"
          fill="freeze"
          dur="2s"
          ref={(animationH) => this.animationH = animationH}
        />
        <animate 
          attributeName="y"
          from="935"
          to="735"
          fill="freeze"
          dur="2s"
          ref={(animationY) => this.animationY = animationY}
        />
        </rect>
      </svg>
    </div>
  );
}

1 个答案:

答案 0 :(得分:0)

它没有更新,因为您通过动画设置heighty的{​​{1}}和<rect>值,这些动画在componentWillMount中触发。您有两种方法可以解决这个问题:

1。更改时触发动画

componentWillMount中的代码解压缩到新方法animate,并在更改值时调用它:

// In your component

componentWillMount() {
  this.animate();
}

animate() {
  this.animationH.setAttribute('from', this.animationH.getAttribute('to'));
  this.animationH.setAttribute('to', this.state.value);
  this.animationY.setAttribute('from', this.animationY.getAttribute('to'));
  this.animationY.setAttribute('to', this.state.value);
}

handleChange(event) {
  this.setState({ value: event.target.value }, this.animate.bind(this));
  // 2nd argument is a callback, called after setState is complete (it is potentially async)
}

2。使用CSS过渡而不是触发动画

不要使用SVG动画,只需使用state中的值将属性设置为render - 方法中的rect,并将CSS转换应用于height和{{1 }}。然后,您将在y之后自动呈现正确的值。

工作示例:https://www.webpackbin.com/bins/-Ki4KIR0eSLQrGh2JrAz

setState
// In your component

render() {
  return (
    ...
      <rect
        className="temperature-bar"
        stroke="#979797"
        strokeWidth="2.132"
        fill="#C20C0C"
        filter="url(#filter-1)"
        x="56.8899994"
        y={value}
        width="18"
        height={value}>
    ...
  );
}

我建议

我会尽可能地建议第二种方法,因为它遵循React背后的核心思想:总是基于状态/道具进行渲染(而不是像触发动画时那样在渲染方法之外改变DOM)。 / p>

PS:你需要为rect正确计算// CSS for your component rect.temperature-bar { transition-property: y, height; transition-duration: 2s; transition-timing-function: linear; } y,因为现在结果完全错了,但你可能知道了。