如何更新子组件的状态以单独拖动它们

时间:2018-04-10 08:35:30

标签: javascript reactjs

我想构建一个页面,该页面具有不确定数量的元素(<Rnd></Rnd>),可以使用react-rnd插件拖动并调整其大小。用户最终将能够从DOM中动态添加/删除这些元素。

使用elementId的数组我在页面上输出6个元素,但是当我将它们拖动到它们周围时它们一起移动并且不是独立的,这在使用react-dev-tools检查它们时得到确认铬。

我认为这是因为他们共享相同的状态,但我如何给他们自己的?

我已经分配了一把钥匙,但我不知道接下来要转向哪里。

我的组件如下所示:

import React, { Component } from 'react';
import Rnd from 'react-rnd';
import styled from 'styled-components';
import './BuildTemplate.css';

class BuildTemplate extends Component {
  constructor(props) {
    super(props);
    this.state = {
      width: 200,
      height: 200,
      x: 10,
      y: 10,
    };
  }

  render() {
    const HandleClasses = {
      bottomLeft: 'corner-handle bottom-left',
      bottomRight: 'corner-handle bottom-right',
      topLeft: 'corner-handle top-left',
      topRight: 'corner-handle top-right',
    };

    function LibraryElements(props) {
      const {
        elementIds, className, size, position, resizeHandleClasses, bounds, onDragStop, onResize,
      } = props;
      const elementList = elementIds.map(elementId => (
        <Rnd
          key={elementId.toString()}
          className={`${className} ${elementId.toString()}`}
          size={size}
          position={position}
          resizeHandleClasses={resizeHandleClasses}
          bounds={bounds}
          onDragStop={onDragStop}
          onResize={onResize}
        >{elementId}
        </Rnd>));
      return (
        elementList
      );
    }

    const elementIds = [1, 2, 3, 4, 5, 6];

    return (
      <div>
        <MasterTemplate>
          <LibraryElements
            elementIds={elementIds}
            className="library-element"
            size={{ width: this.state.width, height: this.state.height }}
            position={{ x: this.state.x, y: this.state.y }}
            resizeHandleClasses={HandleClasses}
            bounds="parent"
            onDragStop={(e, d) => { this.setState({ x: d.x, y: d.y }); }}
            onResize={(e, direction, ref, delta, position) => {
          this.setState({
            width: ref.offsetWidth,
            height: ref.offsetHeight,
            ...position,
          });
        }}
          >Test
          </LibraryElements>
        </MasterTemplate>

      </div>
    );
  }
}

export default BuildTemplate;

const MasterTemplate = styled.div`
  width: 900px;
  height: 500px;
  border: 1px solid #ccc;
  position: relative;
  display: block;
  margin: 30px;
  background: #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
`;

1 个答案:

答案 0 :(得分:1)

访问相同的状态数据会使Rnd组件具有相同的行为。给他们不同的ID对此无能为力。

我建议您删除elementIds;相反,使用位置数组初始化状态,每个生成的Rnd组件将仅更新该数组中的一个项目。

class BuildTemplate extends Component {
  constructor(props) {
    super(props);
    this.state = {
      elements: Array.from({ length: 6 }, () => ({ x : 10, y: 200, width: 200, height: 200 }))
    };
  }

  render() {
    const HandleClasses = {
      bottomLeft: 'corner-handle bottom-left',
      bottomRight: 'corner-handle bottom-right',
      topLeft: 'corner-handle top-left',
      topRight: 'corner-handle top-right',
    };

    function LibraryElements(props) {
      const {
        initialData, className, resizeHandleClasses, bounds, onDragStop, onResize,
      } = props;
      const elementList = initialData.map((item, index) => (
        <Rnd
          key={(index + 1).toString()}
          className={`${className} ${(index + 1).toString()}`}
          size={{ width: item.width, height: item.height}}
          position={{ x: item.x, y: item.y }}
          resizeHandleClasses={resizeHandleClasses}
          bounds={bounds}
          onDragStop={(...args) => onDragStop(index, ...args)}
          onResize={(...args) => onResize(index, ...args)}>
          {(index + 1)}
        </Rnd>));
      return (
        elementList
      );
    }


    return (
      <div>
        <MasterTemplate>
          <LibraryElements
            initialData={this.state.elements}
            className="library-element"
            size={{ width: this.state.width, height: this.state.height }}
            resizeHandleClasses={HandleClasses}
            bounds="parent"
            onDragStop={(index, e, d) => {
              let elements = this.state.elements;
              elements[index] = {
                ...elements[index],
                x: d.x,
                y: d.y
              };
              this.setState({
                elements: elements
              })
            }}
            onResize={(index, e, direction, ref, delta, position) => {
              let elements = this.state.elements;
              elements[index] = {
                ...elements[index],
                width: ref.offsetWidth,
                height: ref.offsetHeight
              };
              this.setState({
                elements: elements
              })
        }}
          >Test
          </LibraryElements>
        </MasterTemplate>

      </div>
    );
  }
}