javascript - 在 React 中为 div 列表设置动画

标签 javascript reactjs animation

我正在 React 中试验简单的动画,试图根据 setInterval 和“移动”功能移动所有蓝色 div。单击背景上的某处时会创建 Div。我找到了一种通过将 this.addDiv(event) 添加到 componentDidMount 来为所有 div 设置动画的解决方案,但在控制台中显示了不可预测的结果。 this.state.position 的状态显示为 NaN。另一个问题是第一个创建的 div 不会立即移动(直到下次单击后才会更新)。 除此之外,我担心代码看起来很难看并且不符合 React 逻辑。

关于如何改进这个动画有什么想法吗?

准备编辑的代码(您需要在 componentDidMount 中取消注释 this.addDiv(event))-> https://codesandbox.io/s/73x3ljq6z0

import React from "react";
import ReactDOM from "react-dom";

const styleApp = {
  textAlign: 'center',
  width: '100vw',
  height: '100vh'
}


class App extends React.Component {
  constructor() {
    super();
    this.state = {
      position: [],
      intervalId: null
    };
  }

  componentDidMount() {
    const intervalId = setInterval(() => {
      this.move()
      this.renderList()
      //this.addDiv(event)  //start moving almoust all div's, without first one. In the console this.state.position show: NaN
      }, 1000);
    this.setState({ intervalId });
  }

  componentWillUnmount() {
    clearInterval(this.state.intervalId);
  }

  addDiv = event => {
    const newStateArray = [...this.state.position];
    newStateArray.push([event.pageX, event.pageY]);
    this.setState({
      x: event.pageX,
      y: event.pageY,
      position: newStateArray
    });
    this.setState((state) => {
      console.log(`positions for all clicks: ${state.position}`);
    });
  };
  move = () => {
    this.setState((state, props) => {
        state.position.forEach((item, index) => {
          let i = item;
          i[0] += 20;
          i[1] += 1;
          console.log(i);
        })
    });
  };

  renderList = () => {
    return ( <div> 
      {this.state.position.map((item, index) => (
        <div
          key={index}
          style={{
            position: "absolute",
            width: "30px",
            height: "30px",
            background: "blue",
            top: this.state.position[index][1],
            left: this.state.position[index][0]
          }}
        />
      ))}
      </div> )
  }

  render() {
    return (
      <div onClick={this.addDiv} className="App" style={styleApp}>
        <p>This is x: {this.state.x}</p>
        <p>This is y: {this.state.y}</p>
        <div>
          { this.renderList() }
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

最佳答案

事物不更新的主要问题是你正在改变状态。

除非感知到差异,否则 React 不会更新状态,并且它使用严格的相等性检查来进行快速检查。因此,您需要确保返回一个新对象,并且需要确保在对 setState 进行函数调用时返回某些内容。这是带有一些内联注释的 move 方法

move = () => {
  this.setState((state, props) => {
    // foreach does not return anything
    state.position.forEach((item, index) => {
      let i = item;
      // these next two lines mutate the array in place
      i[0] += 20;
      i[1] += 1;
      console.log(i);
    })
  });
};

通常,当您调用 setState 时,您想要实际设置状态,所以这里使用 map 而不是 forEach并返回新数组。

move = () => {
  // setState expects a new object for a state, below the `prev => ({})` syntax
  // implicitly returns a new object
  this.setState(prev => ({
    // spread the previous state
    ...prev,
    // map returns a new array, and our implementation, here, returns new sub-arrays and uses some destructuring to make the code easier to read.
    position: prev.position.map(([x, y], index) => [x + 20, y + 1]),
  }));
};

关于javascript - 在 React 中为 div 列表设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53636294/

相关文章:

javascript - webpack (react-scripts) index.html 中的 JS 在做什么?

reactjs - React - 收到非 bool 属性 `false` 'attrName'

reactjs - Typescript 编译器不强制执行泛型

javascript - 使用 React Native 为数组中的每个对象打印图像

javascript - 使用 angularjs 获取休息服务

javascript - 从触发事件 jquery 中排除类

java - 在 Java 中获取操作系统动画首选项

ios - 动画重复时更改 View 的颜色

silverlight - 删除 Silverlight 动画

javascript - 图像 onclick 不起作用